refactor(plugin): hand the cracking-shells marketplace to Nest and reshape the Codex manifest - #15
Merged
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
CrackingShells/Nestis taking over thecracking-shellsmarketplace 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_migrationcampaign's two root leaves.verify/install_checkruns after this lands, because Nest resolvescolgrep-mcpby git source against the default branch — an install cannot see an unmerged branch.What changed
Codex is now served by the root manifest.
plugin.jsoncarriesextensions["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-wiresskills→./skillsand the MCP servers →mcp.jsonby 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.jsonand.agents/plugins/marketplace.jsonare gone..claude-plugin/plugin.jsonand.claude-plugin/mcp.jsonare byte-unchanged — the repository stops publishing a catalogue without stopping being a plugin.The spec declares hub mode. New repo-local
colgrep-mcp.spec.jsonwith"marketplace": {"hub": "https://github.com/CrackingShells/Nest"}, so regenerating can never resurrect a marketplace here. It is byte-identical to the playbook'sassets/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 theAGENTS.mdrepo map.Installs point at Nest.
README.mdanddev/README.mdaddCrackingShells/Nest;@cracking-shellson the right-hand side is unchanged, because the name did not move, only its home. A migration subsection tells existing users toclaude plugin marketplace remove cracking-shellsfirst — 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.authenticationwas"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 toON_INSTALLbefore 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, anddev/skills/maintainer-policy/references/drift-tests.md.landing-and-releasealso describedcz bumpas 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 declaredskillsfield against its own root and requires the product's not to fall insidedev/. 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_filesdropped 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, thatAGENTS.mdgate 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 thatCLAUDE.mdat the plugin root is not loaded as project context. That warning is expected andCLAUDE.mdstays: it is an 11-byte@AGENTS.mdpointer for agents working in a clone, not context meant to travel to users who install the plugin. Recorded instack-trapsas#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.mdis 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
uvxpins still read0.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 tocz bumpto determine from these commits.Verification
Gates on the rebased branch, each re-run by the coordinator after rebase:
uv run pytest— 307 passed, 1 skippeduv run ruff check/ruff format --check— cleanuv run cz check --rev-range main..HEAD— clean, including both merge subjectscheck_plugin.py --root . --spec colgrep-mcp.spec.json— exits 0,ok: plugin structure is consistentclaude plugin validate .(one benign warning, documented above) and./dev— passspawn --dry-run— no writes, no merges; onlykept dev/README.mdGate preconditions verified against the live state rather than taken on report:
known_marketplaces.jsonrecordscracking-shellswith source{"source":"github","repo":"CrackingShells/Nest"}; Nest lists bothcolgrep-mcpandcolgrep-mcp-devwith validON_INSTALLpolicies; the playbook's five plugin roots are on its remote default branch, so Nest'sgit-subdirpaths resolve.verify/install_check— the real marketplace install, server connection and hook firing — runs once this is onmain. 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