Skip to content

refactor(plugin): hand the cracking-shells marketplace to Nest and reshape the Codex manifest - #15

Merged
LittleCoinCoin merged 19 commits into
mainfrom
roadmap/nest-migration
Sep 16, 2026
Merged

LittleCoinCoin merged 19 commits into
mainfrom
roadmap/nest-migration

Conversation

@LittleCoinCoin

Copy link
Copy Markdown
Member

Why

CrackingShells/Nest is taking over the cracking-shells marketplace name as the organisation's single catalogue. Two repositories declaring one marketplace name is a silent replace in Claude Code and a hard error in Codex — a user who added both would get a truncated catalogue with no warning. This hands the name across and moves this repository's manifests to the reshaped generator's output.

Closes the nest_migration campaign's two root leaves. verify/install_check runs after this lands, because Nest resolves colgrep-mcp by git source against the default branch — an install cannot see an unmerged branch.

What changed

Codex is now served by the root manifest. plugin.json carries extensions["com.openai"] with the full interface block and the Codex hooks path; .codex-plugin/ is deleted. Codex parses an Agent-Plugins-conformant root manifest natively and auto-wires skills./skills and the MCP servers → mcp.json by convention, so the fields those files carried are either present in the extensions block or supplied by convention. Verified field-by-field against the deleted files rather than assumed.

This repository no longer publishes a catalogue. .claude-plugin/marketplace.json and .agents/plugins/marketplace.json are gone. .claude-plugin/plugin.json and .claude-plugin/mcp.json are byte-unchanged — the repository stops publishing a catalogue without stopping being a plugin.

The spec declares hub mode. New repo-local colgrep-mcp.spec.json with "marketplace": {"hub": "https://github.com/CrackingShells/Nest"}, so regenerating can never resurrect a marketplace here. It is byte-identical to the playbook's assets/examples/colgrep-mcp.spec.json; that parity is load-bearing, because the playbook's regeneration guard drives its copy against this repository, so any divergence leaves the guard green while measuring a spec nobody uses. Recorded in the AGENTS.md repo map.

Installs point at Nest. README.md and dev/README.md add CrackingShells/Nest; @cracking-shells on the right-hand side is unchanged, because the name did not move, only its home. A migration subsection tells existing users to claude plugin marketplace remove cracking-shells first — a client keeps whichever marketplace it registered under a name at add time, so skipping the remove silently keeps the old two-plugin catalogue with no error.

A Codex policy value that made the catalogue unparseable. policy.authentication was "NONE", which is not in Codex's enum (ON_INSTALL | ON_USE, no catch-all); an invalid value there makes the whole file unparseable rather than degrading one entry. Repaired to ON_INSTALL before the file was deleted, so the broken state did not persist through the gated window.

Drift this surfaced

Nothing in this repository guards prose against manifest shape, and retiring .codex-plugin/ left five stale references — README.md (×2), AGENTS.md's repo map, CONTRIBUTING.md, and dev/skills/maintainer-policy/references/drift-tests.md. landing-and-release also described cz bump as rewriting four manifests and three MCP pins; the real numbers are three and two. All corrected here. Worth noting the last one hid because the counts wrap across a line break, so a line-oriented grep for the phrase does not match it.

Two guards repaired

  • test_dev_plugin.py — the disjoint-placement guard lost its subject with the catalogue and was repointed at the surviving manifests, but its third assertion compared two hardcoded literal paths, which can never be equal. It now resolves each plugin's declared skills field against its own root and requires the product's not to fall inside dev/. Confirmed falsifiable by mutation rather than assumed.
  • test_manifests.py / test_version.py / test_hooks.py — ported from .codex-plugin/* to the shared root manifest and its extensions block. A reviewer pass confirmed coverage moved rather than shrank: no test function was deleted, one was added for the Codex interface block, and the single narrowed assertion narrowed because a third comparison would now be a tautology.

[tool.commitizen].version_files dropped its two .codex-plugin/* entries, which would otherwise have errored at the next release.

A gate that was weaker than it looked

claude plugin validate . validates one manifest, prefers .claude-plugin/marketplace.json, and stops. So while this repository shipped a catalogue, that AGENTS.md gate was checking the marketplace and never the plugin manifest. Deleting the marketplace made it reach the plugin for the first time, surfacing a latent warning that CLAUDE.md at the plugin root is not loaded as project context. That warning is expected and CLAUDE.md stays: it is an 11-byte @AGENTS.md pointer for agents working in a clone, not context meant to travel to users who install the plugin. Recorded in stack-traps as #validate-picks-one, because the masking is the hazard, not the warning.

Deliberately not done

Historical records still carry the old install snippet — __reports__/repo_health/04-findings_remote_install_v0.md is a dated finding, and rewriting it to match present reality would destroy the evidence trail. The leaf's own consistency check could not pass as written because it swept those paths; the corrected sweep excludes __roadmap__ and __reports__.

No version change: every manifest and both uvx pins still read 0.5.1, which is live on PyPI, so the plugin stays launchable throughout. The release is a separate, deliberate step after the install check, left to cz bump to determine from these commits.

Verification

Gates on the rebased branch, each re-run by the coordinator after rebase:

  • uv run pytest — 307 passed, 1 skipped
  • uv run ruff check / ruff format --check — clean
  • uv run cz check --rev-range main..HEAD — clean, including both merge subjects
  • check_plugin.py --root . --spec colgrep-mcp.spec.json — exits 0, ok: plugin structure is consistent
  • claude plugin validate . (one benign warning, documented above) and ./dev — pass
  • spawn --dry-run — no writes, no merges; only kept dev/README.md
  • no conflict markers

Gate preconditions verified against the live state rather than taken on report: known_marketplaces.json records cracking-shells with source {"source":"github","repo":"CrackingShells/Nest"}; Nest lists both colgrep-mcp and colgrep-mcp-dev with valid ON_INSTALL policies; the playbook's five plugin roots are on its remote default branch, so Nest's git-subdir paths resolve.

verify/install_check — the real marketplace install, server connection and hook firing — runs once this is on main. That is the only path that reproduces the "Duplicate hooks file detected" class of failure, which this repository has hit before at 0.4.0 and 0.5.0.

🤖 Generated with Claude Code

LittleCoinCoin and others added 19 commits September 16, 2026 01:11
Four nodes at depth 1. relinquish_marketplace and regenerate_manifests share
no files, so they are siblings; only the install check needs both.

This campaign is fully gated on the playbook's agent_plugin_nest campaign
reaching its end-to-end install verification. Relinquishing a working
catalogue before its replacement is proven would leave users with neither,
so the gate is recorded in the campaign pre-conditions rather than left to
scheduling.

Facts established while authoring:

- Both marketplace files here declare the name cracking-shells, and the
  Claude one lists colgrep-mcp-dev alongside colgrep-mcp. Nest must carry
  both before either file is deleted.
- .codex-plugin/ exists today, so the regenerate leaf's absence check is
  meaningful rather than vacuous.
- regenerate_manifests needs --force, which is safe for put but makes
  merge_marketplace replace a marketplace wholesale. It is only safe here
  because relinquish_marketplace deletes both marketplace files first; the
  leaf says so and tells the implementer to stop if they are still present.
- Three references pointed at skills/spawning-agent-plugins/ as if it lived
  in this repository. It does not: this repo has skills/colgrep-search and
  dev/skills/. They now point at the playbook's copy by URL.
Regenerating with the unchanged spec would write both marketplace files back,
silently undoing relinquish_marketplace and restoring the two-owner collision
this migration exists to remove. Switching the spec to hub mode first removes
the hazard and makes the two leaves genuinely order-independent, which is what
their sibling placement already claimed.

The campaign gate is now stated per leaf: regenerate_manifests needs only the
reshaped generator, while relinquish_marketplace waits for Nest to be proven.
Level 0 status, set through dirtree-rdm only.

`regenerate_manifests` is in progress: its gate is open. The playbook's
`generator_reshape` leaf is merged at d7e2ac8 on roadmap/agent-plugin-nest,
and the generator on disk there carries the reshape (references com.openai,
none to codex-plugin) rather than merely claiming it in a status table.

`relinquish_marketplace` is blocked, not planned. Its gate is the playbook's
`generator/rollout/verify/end_to_end` leaf, which is still planned, as are
both rollout leaves above it. Concretely: the playbook has no plugins/
directory, so the five git-subdir paths CrackingShells/Nest points at do not
resolve, and Nest itself is unpushed. Nothing can install from Nest today, so
this repository cannot yet give up a working catalogue.

`verify/` is blocked behind both siblings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add top-level "marketplace": "hub" to a repo-local copy of the generator
spec, colgrep-mcp.spec.json, so `spawn_plugin.py spawn` never calls
merge_marketplace and this repo stops resurrecting either marketplace
file once regenerated (spawn_plugin.py:608-616 keys hub mode off this one
truthy field, per SKILL.md's "Does another repo own the marketplace
name?" row and references/manifests.md's hub-mode section).

Deviates from the leaf spec's Step 1 in two ways, both directed by the
coordinator:

1. The spec lives at repo root (colgrep-mcp.spec.json), not at the
   playbook's assets/examples/colgrep-mcp.spec.json. That file is the
   fixture for the playbook's own regeneration guard
   (skills/spawning-agent-plugins/evals/test_regeneration.py) and is out
   of scope for this migration; editing it in place would re-baseline
   someone else's tripwire from inside this repo. This repo now carries
   its own spec, and the playbook's example has diverged from it.

2. claude_marketplace.name and codex.marketplace_name are KEPT at
   "cracking-shells" rather than dropped, contrary to
   references/manifests.md's general hub-mode guidance ("a spec bound
   for a hub carries no claude_marketplace or codex.marketplace_name
   section at all"). Hub mode is keyed only off the top-level
   `marketplace` field (spawn_plugin.py:612), but
   `claude_marketplace.name` is separately read by dev_readme() at
   spawn_plugin.py:599/601 to render dev/README.md's install snippet,
   and by install_snippet() at spawn_plugin.py:744, both falling back to
   "colgrep-mcp-marketplace" when the key is absent. Dropping the name
   fields would silently rewrite dev/README.md to advertise
   colgrep-mcp-dev@colgrep-mcp-marketplace, a marketplace that does not
   exist. The marketplace name itself is not moving in this campaign,
   only its home (to CrackingShells/Nest), so the fields stay as
   documentation-only inputs.

Consistency check:
    $ test ! -f .claude-plugin/marketplace.json || echo "marketplace still present - relinquish has not run yet, which is allowed"
    marketplace still present - relinquish has not run yet, which is allowed
(PASS — relinquish_marketplace is a separate, currently-gated leaf.)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…espace

Regenerate the manifests from the repo-local spec with the reshaped
generator, then delete .codex-plugin/ (the generator no longer writes it
but does not remove what an earlier run left behind).

Command run, from this worktree, invoking the checkout on
roadmap/agent-plugin-nest (the branch containing the reshape):

    python3 /Users/.../cracking-shells-playbook/skills/spawning-agent-plugins/scripts/spawn_plugin.py \
      --root . spawn --spec colgrep-mcp.spec.json --force

Confirmed before trusting it that this checkout is the reshaped
generator, not the unextended one that would silently regenerate the old
three-manifest shape: `grep -n "com.openai" spawn_plugin.py` matches (6
lines, including build_codex_extensions and the extensions["com.openai"]
assignment in build_agent_plugin), and `grep -n "codex-plugin"
spawn_plugin.py` matches nothing.

Output:
    wrote   plugin.json
    wrote   mcp.json
    wrote   .claude-plugin/plugin.json
    wrote   .claude-plugin/mcp.json
    wrote   hooks/hooks.json
    wrote   hooks/worktree-remove.json
    wrote   dev/.claude-plugin/plugin.json
    wrote   dev/README.md

No "merged"/"would merge" line for either marketplace file, confirming
hub mode suppressed both.

Diff summary:
- plugin.json: gains extensions["com.openai"] (interface block + hooks
  pointer to ./hooks/hooks.json); identity fields unchanged.
- mcp.json, .claude-plugin/mcp.json, .claude-plugin/plugin.json,
  dev/.claude-plugin/plugin.json: pretty-printed keywords/args arrays
  only (json.dumps(indent=2) vs. the hand-authored single-line arrays);
  no field changes.
- hooks/hooks.json, hooks/worktree-remove.json: byte-identical, so the
  writer skipped them (no diff in git status).
- dev/README.md: regenerated from the generator's dev_readme() template;
  still names "cracking-shells" (`claude plugin install
  colgrep-mcp-dev@cracking-shells`), confirmed by hand-diffing against
  the pre-regeneration file. Loses a few hand-written sentences
  (CONTRIBUTING mention, evals/ cases) the template does not carry —
  cosmetic, not a shape change, and within this leaf's scope of
  regenerating from the spec.
- .agents/plugins/marketplace.json, .claude-plugin/marketplace.json:
  untouched (git status shows neither), as hub mode requires.
- .codex-plugin/: deleted (mcp.json, plugin.json), the generator's own
  authoritative shape no longer writes this directory.

Consistency check:
    $ test ! -d .codex-plugin && python3 -c "import json;d=json.load(open('plugin.json'));assert 'com.openai' in d['extensions']"
    CONSISTENCY CHECK PASS

Version confirmed unchanged at 0.5.1 in every regenerated manifest and
in the uvx pin (mcp.json, .claude-plugin/mcp.json both still pin
colgrep-mcp==0.5.1); resolve_version() read it from
server/pyproject.toml via version_from, never bumping it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Update the drift guards that hard-coded the retired three-manifest shape,
and the commitizen version_files list that would otherwise try to rewrite
a version string into two files .codex-plugin/ no longer contains.

Guards updated, and why (each encoded ".codex-plugin/{plugin,mcp}.json"
as a real file rather than as one of Codex's checks against the shared
root manifest):

- server/tests/test_manifests.py: MCP_MANIFESTS dropped
  ".codex-plugin/mcp.json"; test_versions_aligned, test_names_aligned,
  test_placeholders_only_in_claude_code_env and
  test_plugin_manifests_point_at_their_own_mcp_file no longer read
  ".codex-plugin/plugin.json" (Codex now shares plugin.json/mcp.json with
  Agent Plugins 1.0, already covered by the assertions against those
  files). Added test_codex_extension_carries_the_interface_block, ported
  from check_plugin.py's _check_codex_interface, so this repo's own guard
  suite pins the extensions["com.openai"].interface shape directly
  instead of relying only on the playbook's external checker.
- server/tests/test_version.py: same rationale for
  test_manifests_match_pyproject and test_mcp_manifests_pin_the_pyproject_version.
- server/tests/test_hooks.py: test_manifests_name_the_hook_files_per_ecosystem
  now reads Codex's hooks pointer from plugin.json's
  extensions["com.openai"].hooks instead of a nonexistent
  .codex-plugin/plugin.json.
- server/pyproject.toml: [tool.commitizen].version_files dropped
  "../.codex-plugin/plugin.json:\"version\"" and
  "../.codex-plugin/mcp.json:colgrep-mcp==". These are not test code, but
  belong in this step for the same reason: cz bump would otherwise try to
  rewrite a version string into two files that no longer exist. Caught by
  running `cz bump --dry-run` after Step 2 and noticing it needed
  verifying, not by a failing test (commitizen does not appear to
  validate version_files entries during --dry-run, so this would have
  first surfaced at a real release).

Gate output, run from this worktree:

    $ cd server && uv run pytest
    307 passed, 1 skipped, 21 warnings in 16.48s

    $ cd server && uv run ruff check
    All checks passed!

    $ cd server && uv run ruff format --check
    46 files already formatted

    $ cd server && uv run cz check --rev-range roadmap/nest-migration..HEAD
    Commit validation: successful!

    $ cd server && uv run cz bump --dry-run
    release(colgrep-mcp): v0.5.2
    tag to create: v0.5.2
    increment detected: PATCH
    (dry run only; server/pyproject.toml was not bumped, version stays 0.5.1)

    $ claude plugin validate .
    Validating marketplace manifest: .../.claude-plugin/marketplace.json
    Validation passed

    $ claude plugin validate ./dev
    Validating plugin manifest: .../dev/.claude-plugin/plugin.json
    Validation passed

    $ python3 .../cracking-shells-playbook/skills/spawning-agent-plugins/scripts/check_plugin.py --root . --spec colgrep-mcp.spec.json
    - .agents/plugins/marketplace.json: colgrep-mcp policy.authentication is invalid: 'NONE'
    1 problem(s)

Version confirmed 0.5.1 in plugin.json, .claude-plugin/plugin.json,
dev/.claude-plugin/plugin.json, and the uvx pin in mcp.json and
.claude-plugin/mcp.json. No marketplace file reappeared: git status shows
neither .claude-plugin/marketplace.json nor .agents/plugins/marketplace.json
touched by this branch.

DEFECT, not fixed here: the check_plugin.py problem above and the leaf
spec's own Step 3 consistency check
(`test ! -f .claude-plugin/marketplace.json`, expected PASS) both fail,
and for the same reason — the pre-existing .agents/plugins/marketplace.json
(with its known "NONE" authentication bug) and .claude-plugin/marketplace.json
are both still present, because relinquish_marketplace, the sibling leaf
that retires them, has not run yet. This brief explicitly directs leaving
both files alone ("Hub mode means the generator won't rewrite them; that
is the expected, correct outcome for this leaf") and the campaign README
states regenerate_manifests "can start earlier than its sibling"
relinquish_marketplace. Both statements are correct, and together they
guarantee the Step 3 consistency check and success-gate 4
("check_plugin.py reports no problems") cannot pass whenever this leaf
runs before relinquish_marketplace — which the roadmap explicitly permits.
Reported to the coordinator rather than worked around by touching a file
this leaf was told not to touch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…clobbered

Regenerating with `--force` overwrote `dev/README.md` from the generator's
`dev_readme()` template, losing hand-maintained content that the template
cannot know about:

  - where the dev plugin's eval cases live (`evals/` under `dev/evals/`)
  - the attribution of the progressive-disclosure layout to skill-creator
  - the CONTRIBUTING framing ("human projects say install the dev
    environment; here the dev environment is knowledge")

This file is deliberately divergent from the template, which is why the
playbook's regeneration guard carries it as a whole-file exemption
(`ALLOWED_DIVERGENCE["dev/README.md"] = None`, "hand-maintained prose with
no JSON keys to compare"). The reshape leaf had no mandate to rewrite it;
only the manifests were in scope.

The `@cracking-shells  # from the repo's own marketplace` line is left as
it stands: it is still accurate while this repository's marketplace files
exist, and repointing it at CrackingShells/Nest belongs to
`relinquish_marketplace` step 2, which explicitly owns the install snippet
wherever it is reproduced.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ex-plugin is gone

Deleting `.codex-plugin/` left five prose references to it, none of which any
test pins. A reviewer pass found three; two more were in the README, the most
user-visible of the set.

  - `README.md` install section: the Codex manifests are now
    `.agents/plugins/marketplace.json` and the root `plugin.json`.
  - `README.md` packaging section: the Codex plugin is served by the root
    manifest's `extensions["com.openai"]` block, with `skills` and the MCP
    servers auto-wired by convention rather than named in their own files.
  - `AGENTS.md` repo map: dropped `.codex-plugin/` from the path column and
    the MCP config list, which is now two files, not three.
  - `CONTRIBUTING.md`: the `uvx` pin lives in two MCP manifests, not three.
  - `dev/skills/maintainer-policy/references/drift-tests.md`: three plugin
    manifests, not four; two MCP configs, not three; and `test_manifests.py`
    now also pins the `extensions["com.openai"]` interface block, which is
    how Codex is served.

Marketplace references in these files are deliberately left alone: this
repository still declares `cracking-shells` until `relinquish_marketplace`
lands, and that leaf owns repointing every install snippet at
CrackingShells/Nest.

Nothing guards prose against manifest shape, which is why this drift was
silent. Noted for the campaign's knowledge-transfer report rather than fixed
here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…a com.openai extensions, hub mode, .codex-plugin retired)

Closes the `regenerate_manifests` leaf of the nest_migration campaign. This
repository's manifests now come from the reshaped generator: Codex is served
by the root Agent-Plugins `plugin.json` through its `extensions["com.openai"]`
block, and `.codex-plugin/` is gone.

The spec is now repo-local (`colgrep-mcp.spec.json`) and declares
`marketplace: "hub"`, so regeneration writes no marketplace file here. It
differs from the playbook's `assets/examples/colgrep-mcp.spec.json` by exactly
that one key; the playbook's copy was deliberately not edited, being the
fixture for its own regeneration guard.

`claude_marketplace.name` and `codex.marketplace_name` are kept at
`cracking-shells` rather than deleted. Hub mode keys only off the top-level
`marketplace` key (spawn_plugin.py:596), while those two names are separately
consumed to render `dev/README.md` (:583) and the install snippet (:728), both
falling back to a nonexistent `colgrep-mcp-marketplace`. The leaf spec called
for deleting them; that was a defect and is corrected here.

Verified by a dispatched adversarial reviewer, which recomputed every diff
independently, recovered the deleted `.codex-plugin/*` files and compared them
field-by-field against the new extensions block, and traced hub mode through
the generator's control flow. It confirmed the drift guards moved rather than
shrank: no test function was deleted, one was added covering the Codex
interface block, and the one assertion that narrowed did so because a third
comparison would now be a tautology.

Gates on the rebased branch: pytest 307 passed / 1 skipped; ruff check and
format clean; cz check clean; claude plugin validate passes for both plugins;
no .codex-plugin/; plugin.json carries extensions["com.openai"]; version held
at 0.5.1 in every manifest and both uvx pins.

Two things this leaf deliberately did not do. `check_plugin.py` still reports
one problem — the pre-existing `"authentication": "NONE"` in
`.agents/plugins/marketplace.json`, a value absent from Codex's enum. That
file is deleted by `relinquish_marketplace`, which is gated, so the leaf's
Success Gate 4 as literally written is unsatisfiable in the ordering the
campaign README explicitly permits; the reviewer confirmed it is the only
problem reported. And every install snippet still names this repository's
marketplace, which remains accurate until that same leaf lands.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s gate

Set through dirtree-rdm. The level does not close: `relinquish_marketplace`
and `verify/` remain blocked on the playbook campaign, so nest_migration is
half-landed by design rather than stalled.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`policy.authentication` was `"NONE"`, which is not in Codex's enum
(`ON_INSTALL | ON_USE`, with no catch-all). An invalid value there does not
degrade one entry — it makes the whole marketplace file unparseable, so a
Codex user adding this repository could install nothing at all from it.

The value came from the generator, which hardcoded `"NONE"` in Codex
marketplace entries; that is fixed upstream, where `build_codex_marketplace`
now emits `"ON_INSTALL"`. This file predates the fix and is no longer
regenerated here, because the spec declares hub mode and writes no
marketplace at all — so the bad value would have survived until the file was
deleted rather than being corrected by a later run.

`ON_INSTALL` matches both the upstream generator's output and every entry in
CrackingShells/Nest's own Codex catalogue, so the two catalogues agree for as
long as both exist during the transition.

`relinquish_marketplace` deletes this file outright once CrackingShells/Nest
can provably install plugins. That leaf is gated on the playbook campaign and
may stay gated for some time, which is the reason to repair the file now
rather than wait for its deletion: the broken state is user-visible in the
meantime.

Side effect worth recording: this closes `regenerate_manifests`' Success Gate
4 (`check_plugin.py` reports no problems), which that leaf merged against as
a documented exception because the only problem reported was this value.
`check_plugin.py --root . --spec colgrep-mcp.spec.json` now exits 0 with
"ok: plugin structure is consistent".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The generator's `load_spec` no longer accepts a bare `"marketplace": "hub"`
sentinel: hub mode must name the repository that owns the marketplace, and a
spec without it is refused outright (exit 2, with a message naming the key to
add). Our spec carried the bare sentinel, so the next `spawn` against it would
have failed rather than regenerated.

The shape is now `"marketplace": {"hub": "https://github.com/CrackingShells/Nest"}`,
which also lets `install_snippet` name the hub's slug instead of this
repository's own — the defect that made its output wrong for us.

With this key the spec is byte-identical to the playbook's
`assets/examples/colgrep-mcp.spec.json`, which has moved to hub mode too. That
parity is load-bearing rather than incidental: the playbook's regeneration
guard drives `spawn` with *its* copy against *this* repository, so any key
where the two disagree leaves the guard green while measuring a spec nobody
uses. Recorded in the repo map so the constraint outlives this campaign — the
file was missing from that table, which was itself leftover drift from
`regenerate_manifests` adding it.

Dry run against the updated spec reports no writes and no merges; the only
entry is `kept dev/README.md`, which is now create-only in the generator and
cannot be clobbered by `--force`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`landing-and-release` still described `cz bump` as rewriting four
version-tracked manifests and a pin in three MCP manifests. Retiring
`.codex-plugin/` left three and two respectively, per
`[tool.commitizen].version_files`: `plugin.json`,
`.claude-plugin/plugin.json` and `dev/.claude-plugin/plugin.json` carry the
version, and the `uvx colgrep-mcp==<version>` pin lives in
`.claude-plugin/mcp.json` and the root `mcp.json`.

This is the release-mechanics skill, so a wrong count here is worse than
prose drift: a maintainer reconciling a version-drift failure would look for
a fourth manifest that does not exist and could conclude the bump had
half-failed.

Found only because the numbers wrap across a line break, which a
line-oriented grep for "four version-tracked" does not match — the same
reason the earlier sweep for this drift missed it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…Shells/Nest

Nest is live and lists both colgrep-mcp and colgrep-mcp-dev under the
cracking-shells name, so this repository no longer needs to publish its
own catalogue. Delete .claude-plugin/marketplace.json and
.agents/plugins/marketplace.json; .claude-plugin/plugin.json and
.claude-plugin/mcp.json are untouched, since a plugin stops publishing a
catalogue without ceasing to be a plugin. Deleting both files left
.agents/ with nothing in it, and it was pruned from the working tree
along with them (git tracks no empty directories).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ration

Repoint the Claude Code and Codex marketplace-add commands at
CrackingShells/Nest in README.md, dev/README.md and AGENTS.md; the
plugin install commands (`colgrep-mcp@cracking-shells`,
`colgrep-mcp-dev@cracking-shells`) are unchanged, since the marketplace
name did not move, only its home. Add a README subsection telling
existing users to `marketplace remove cracking-shells` before adding
Nest, since a client keeps whichever repository it registered under a
name at add time and would otherwise silently keep resolving to this
repository's now-deleted, unpublished catalogue. Also correct two
README passages that still described `.agents/plugins/marketplace.json`
as a live Codex manifest and `.claude-plugin/marketplace.json` as this
repo's own catalogue; both files are gone as of the prior commit.

Update the server/tests/test_dev_plugin.py drift guard
(test_marketplace_lists_both_plugins_from_disjoint_sources), which
read the two plugins' name/source pairs out of the now-deleted
.claude-plugin/marketplace.json. Renamed to
test_product_and_dev_plugins_are_named_and_placed_disjointly, it now
checks the same fact -- that colgrep-mcp and colgrep-mcp-dev are two
disjoint plugins at disjoint locations -- from the two plugin.json
manifests that still exist, since the catalogue itself now lives in
CrackingShells/Nest rather than in this repository.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Deleting `.claude-plugin/marketplace.json` cost this guard its subject: it
read both plugins' names and sources out of the catalogue, and the catalogue
now lives in CrackingShells/Nest. Repointing it at the two surviving
manifests was right, but its third assertion compared two hardcoded manifest
paths:

    assert (REPO_ROOT / "dev" / ".claude-plugin" / "plugin.json").resolve()
        != (REPO_ROOT / ".claude-plugin" / "plugin.json").resolve()

Distinct literals are never equal, so that assertion cannot fail. It reads
like a placement check while guarding nothing — the same shape as the
tautology the reviewer pass was told to hunt for in the sibling leaf, arrived
at here by a different route.

Replaced with a check on the values the manifests actually declare: resolve
each plugin's own `skills` field against its own plugin root, require both to
exist, to differ, and the product's not to fall inside `dev/`. That restores
the original intent — the two plugins are rooted at disjoint sources — as
something a future edit can break.

Confirmed falsifiable rather than assumed: repointing the product manifest's
`skills` at `./dev/skills/` fails the test; the manifest was restored and the
tree left clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Deleting the marketplace made `claude plugin validate .` emit a warning it
had never emitted before, about `CLAUDE.md` at the plugin root not being
loaded as project context. The implementer reported the warning as
pre-existing. The condition is; the warning is not.

`claude plugin validate <dir>` validates exactly one manifest, preferring
`.claude-plugin/marketplace.json` and stopping there. While this repository
shipped its own catalogue, the `AGENTS.md` gate `claude plugin validate .`
was therefore checking the marketplace and never the plugin manifest — every
green result in this repository's history said less than it looked like.
Removing the marketplace made the command fall through to the plugin for the
first time, which surfaced a latent warning rather than introducing one.

The warning itself is benign and `CLAUDE.md` stays: it is an eleven-byte
`@AGENTS.md` pointer for agents working in a clone, not context meant to
travel to users who install the plugin, and the knowledge it points at ships
separately as the colgrep-mcp-dev skills. The validator is correct that it
does nothing for an installed plugin.

Recorded as a trap because the masking is the hazard, not the warning: a
validator that changes which manifest it inspects depending on what it finds
makes "validation passed" only as strong as the manifest it happened to pick.
The first line of its output names that manifest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…place handed to Nest, installs repointed, guards repaired)

Closes the `relinquish_marketplace` leaf. This repository no longer declares
the `cracking-shells` marketplace: `.claude-plugin/marketplace.json` and
`.agents/plugins/marketplace.json` are deleted, and CrackingShells/Nest is now
the organisation's only catalogue under that name. `.claude-plugin/plugin.json`
and `.claude-plugin/mcp.json` are byte-unchanged — the repository stops
publishing a catalogue without stopping being a plugin.

Unblocked by the playbook campaign, verified here rather than taken on report:
Nest is pushed at eb3a7eb listing both `colgrep-mcp` and `colgrep-mcp-dev` with
valid ON_INSTALL policies, the playbook's five plugin roots are on its remote
default branch so Nest's git-subdir paths resolve, and the local
`cracking-shells` registration records source
{"source":"github","repo":"CrackingShells/Nest"} — the source, not just the
name.

README and dev/README.md now add CrackingShells/Nest; `@cracking-shells` on the
right-hand side is unchanged, because the marketplace name did not move, only
its home. A migration subsection tells existing users to
`marketplace remove cracking-shells` first: a client keeps whichever
marketplace it registered under a name at add time, so skipping the remove
silently keeps the old two-plugin catalogue with no error.

Historical records were deliberately left carrying the old snippet —
`__reports__/repo_health/04-findings_remote_install_v0.md` is a dated finding,
and rewriting it to match present reality would destroy the evidence trail.
The leaf's own consistency check could not pass as written because it swept
those paths; the corrected sweep excludes `__roadmap__` and `__reports__` and
passes.

Two guards were repaired on the way in, both mine rather than the
implementer's:

  - `test_dev_plugin.py`'s disjoint-placement guard lost its subject with the
    catalogue and was repointed at the two surviving manifests, but its third
    assertion compared two hardcoded literal paths, which can never be equal.
    It now resolves each plugin's declared `skills` field against its own root
    and requires the product's not to fall inside `dev/`. Confirmed
    falsifiable by mutation, not assumed: repointing the product manifest at
    `./dev/skills/` fails it.
  - `stack-traps` gained the reason the validator warning appeared. Deleting
    the marketplace made `claude plugin validate .` reach the plugin manifest
    for the first time: it validates one manifest, prefers the marketplace and
    stops. This repository's own gate was checking the catalogue and never the
    plugin for as long as one existed. The surfaced `CLAUDE.md` warning is
    benign and that file stays.

Gates on the rebased branch: pytest 307 passed / 1 skipped; ruff check and
format clean; cz check clean; check_plugin.py exits 0 with "ok: plugin
structure is consistent"; claude plugin validate passes for the repo (one
benign warning, documented) and for ./dev; no conflict markers.

Not done here: nothing is pushed, so `verify/install_check` remains blocked —
Nest resolves colgrep-mcp against its default branch, so this work must reach
`main` before an install can see it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both root leaves are done: the manifests carry the Codex extensions shape and
this repository no longer declares a marketplace. `verify/` opens, but
`install_check` stays planned until the work reaches `main` on the remote —
Nest resolves colgrep-mcp by git source against its default branch, so an
install cannot see an unpushed campaign branch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@LittleCoinCoin
LittleCoinCoin merged commit a75fb36 into main Sep 16, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant