refactor(toolchain): relocate setup topic-docs offering to the verification plugin that owns it - #737
Conversation
…cation plugin that owns it /toolchain:setup step 6 wrote .claude/topic-docs.yaml — a consumer config resolved by the implementation and verification plugins for artifact placement, not by any /toolchain:* skill. Move the offering to the lifecycle plugin that owns it, matching the established /discovery:setup and /planning:setup pattern. - Add /verification:setup — settles the topic-docs seam (check reports the effective concern; apply persists the tracked .claude/topic-docs.yaml with the committed-tier ignore guard), plus its evals. - Scope /toolchain:setup to the ecosystem command surface it owns: drop the topic-docs report from check, the offering from apply (step 6), and the orphaned reference/topic-docs.md binding only step 6 read. - Update toolchain and verification READMEs; bump both plugins with CHANGELOG entries. Closes #263 Co-Authored-By: Claude <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 14s —— View job PR Review
SummaryThis is a clean ownership refactor: ArchitectureOwnership assignment is correct. Idempotency is properly specified. SKILL.md L27-33 states re-running reads the current state and offers an update, rather than overwriting blind. The non-interactive path (complete Guard before write is correctly placed. SKILL.md L73-76 runs the committed-tier New skill:
|
| Eval | What it tests |
|---|---|
reads-topic-docs-state-before-interview |
State-read-first, defaults for absent keys, all keys offered |
fails-closed-on-ignored-contract-tier |
Guard stops before write; exact rule reported; no gitignore edit |
persists-tracked-concern-file-idempotently |
Schema-valid YAML object; preserves existing keys; memory root self-ignore; no rewrite on re-run |
One edge case worth noting — not a blocker: SKILL.md L76 says "omit keys the user leaves at their defaults, but always write at least one explicit key". In the non-interactive path where a caller passes all four keys at their documented defaults, the guidance is slightly ambiguous — should the model omit all (then write one anyway) or write all? In practice the caller is being explicit about wanting those values, so writing them all is the right call, but the spec doesn't distinguish this sub-case from the interactive "user accepted the recommended default" case. This is an edge case unlikely to be hit in real usage, but a one-line clarification in apply step 2 would eliminate any ambiguity. Fix this →
Hardcoded schema URL: SKILL.md L18 links to https://raw.githubusercontent.com/melodic-software/claude-code-plugins/main/docs/conventions/topic-docs/topic-docs.schema.json. This is a reference URL for consumers to understand the schema — acceptable here since it's intentionally the marketplace's canonical schema location, not a runtime dependency. Consistent with how other skills reference convention docs.
Removed from toolchain
The deletion of reference/topic-docs.md is correct — the PR description confirms it was only referenced by the now-removed step 6 in /toolchain:setup. The trimmed toolchain/skills/setup/SKILL.md correctly retains nothing about topic-docs and stays scoped to the ecosystem command surface.
Versioning
| Plugin | From | To | Reason | Verdict |
|---|---|---|---|---|
toolchain |
0.4.3 | 0.5.0 | Capability removed | ✅ Minor bump for 0.x removal |
verification |
0.2.4 | 0.3.0 | New skill added | ✅ Minor bump for new capability |
Both follow semver convention for pre-1.0 plugins; changelogs use correct Keep a Changelog section headers (Removed / Added).
Validation
The PR reports all CI checks passed:
validate-plugin-contracts.mjs→ 34 setup skills (was 33) ✅generate-catalog.mjs --check→ in sync ✅check-changelog-parity.sh→ every versioned plugin has a CHANGELOG ✅check-skill-leaf-names.sh→setupleaf is open by contract ✅check-changed-skills.sh→ 3 skills checked, 0 errors ✅markdownlint-cli2→ 0 errors ✅
Recommendation: approve. The change is architecturally correct, follows the established pattern, is well-validated, and has no blocking issues.
|
Post-green review pass complete (rule 8). Bot review: no blocking findings — architecture (ownership assignment to verification, matching the discovery/planning/implementation setup-skill pattern) confirmed correct, idempotency and fail-closed guard behavior both correctly specified, evals cover the 3 critical behaviors. One low-priority edge-case wording ambiguity flagged (non-blocker) and one hardcoded schema URL confirmed intentional/acceptable (canonical marketplace schema location, not a runtime dependency). No threads to resolve, CI fully green (13/13). Flipping to ready for review; handing off to the babysit lane for merge. |
|
Claude finished @kyle-sexton's task in 2m 28s —— View job PR Review
SummaryClean ownership refactor. ArchitectureOwnership assignment is correct. Idempotency is properly specified. Guard placement is correct. New skill:
|
| Eval | What it tests |
|---|---|
reads-topic-docs-state-before-interview |
State-read-first; defaults for absent keys; all keys offered |
fails-closed-on-ignored-contract-tier |
Guard uses representative file path; stops before write; reports exact rule; never edits an ignore file |
persists-tracked-concern-file-idempotently |
Schema-valid YAML object; preserves existing keys; memory root self-ignore; no rewrite on re-run |
Spec tension between step 1 and step 2 in apply — non-blocker but worth a one-line fix: SKILL.md L68-69 (step 1) says "preserve every key an existing file carries — a re-run never drops one." SKILL.md L76 (step 2) says "omit keys the user leaves at their defaults." A model following step 2 literally on a re-run could drop an existing key that happens to match a default — contradicting step 1. The intended reading is that the "omit defaults" rule applies only on initial creation (no existing file); on re-run, existing keys are always preserved. Adding "on initial creation" or "when no existing value is present for that key" to step 2 would make this explicit and close the gap. Eval 3's "Preserves all existing schema keys on reconfiguration" expectation does enforce the correct behavior at eval time, but a well-prompted model shouldn't need to infer this from the eval. Fix this →
The prior review flagged the overlapping non-interactive path ambiguity (all 4 keys explicitly passed at their defaults) — both findings stem from the same underspecified boundary between "initial create" and "update" semantics in step 2. One clarifying phrase resolves both.
GitBook deferred-backend spec is consistent. The check step 4 and apply step 1 both describe gitbook as reserved-but-deferred identically, with the same non-writable rationale. No drift.
Hardcoded schema URL at SKILL.md L18 — intentional and acceptable. This is the marketplace's canonical schema location for consumer reference, consistent with how other skills link convention docs. Not a runtime dependency.
Removed from toolchain
The deletion of reference/topic-docs.md is correct — the PR description confirms it was only consumed by step 6 in /toolchain:setup, which is also removed. The trimmed toolchain/skills/setup/SKILL.md stays cleanly scoped to the ecosystem command surface (.claude/ecosystems/*.yaml files) with no residual reference to topic-docs.
Versioning & Changelogs
| Plugin | From | To | Reason | Verdict |
|---|---|---|---|---|
toolchain |
0.4.3 | 0.5.0 | Capability removed | ✅ Minor bump for 0.x removal |
verification |
0.2.4 | 0.3.0 | New skill added | ✅ Minor bump for new capability |
Both changelog entries use the correct Keep a Changelog section headers (Removed / Added), cross-reference #263, and accurately describe what changed.
Validation
Per PR body (all scripts run against origin/main in the worktree):
validate-plugin-contracts.mjs→ 34 setup skills (was 33) ✅generate-catalog.mjs --check→ in sync ✅check-changelog-parity.sh→ every versioned plugin has a CHANGELOG ✅check-skill-leaf-names.sh→setupleaf is open by contract ✅check-changed-skills.sh→ 3 skills checked, 0 errors ✅markdownlint-cli2→ 0 errors on all 6 changed markdown files ✅
Recommendation: approve. One non-blocking spec wording opportunity (step 2 "omit defaults" needs to scope to initial-create only), but the eval already enforces the correct behavior. Architecture is correct, validated, and follows the established pattern.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 30d9121ef3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Completes the toolchain->verification relocation of the topic-docs offering by correcting references the relocation left stale (codex review, #263): - verification/skills/setup/SKILL.md dropped `implementation` from the list of siblings that "offer the same file from its own setup" — implementation has no setup skill; it consumes the concern file but does not offer it. The offering siblings are `discovery` and `planning` (plus this skill). - implementation/README.md repointed from `/toolchain:setup` (which no longer writes `.claude/topic-docs.yaml` after this relocation) to each lifecycle plugin's own setup (`/discovery:setup`, `/planning:setup`, `/verification:setup`). Co-Authored-By: Claude <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 1m 52s —— View job PR Review
SummaryTwo-commit PR — the main refactor ( Latest commit:
|
|
Claude finished @kyle-sexton's task in 3m 24s —— View job Security Review — PR #737
No CRITICAL or IMPORTANT findings. Two SUGGESTION-level observations follow. SUGGESTION — Unquoted path in
|
| Area | Result |
|---|---|
| GitHub Actions workflow files | None changed |
| Shell command injection (scripts) | No scripts in the diff |
| Hardcoded secrets / credentials | None |
| External fetch / data egress | Schema URL is a consumer reference link, not a runtime fetch |
| Supply chain (new dependencies, unpinned actions) | None introduced |
Permission widening (workflow permissions:, settings files) |
None changed |
pull_request_target / workflow_run unsafe patterns |
No workflow changes |
Plugin sandbox compliance (${CLAUDE_PLUGIN_ROOT}, ${CLAUDE_PLUGIN_DATA}) |
Correct — concern file is always written to consumer's .claude/topic-docs.yaml |
| Memory/state written outside consumer repo | Not specified; memory_dir self-ignore creation stays within repo by convention |
disable-model-invocation: true |
Present on both setup skills — correct |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7d3d88d159
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
The 3 shared setup-skill findings left open on this PR (comments 3616655423, 3616882930, 3616882934) are tracked cross-cutting in #745 rather than patched here — they're verbatim-identical in /discovery:setup and /planning:setup too, so a single-plugin fix would diverge the explicitly-mirrored family. |
…13 READMEs (wave 3) (#771) Closes #537 — final wave; repo-wide repro grep (`at the root of|root of (the )?melodic`) returns zero across all `plugins/*/README.md` on this branch. Supersedes #766 (identical change, rebased): #737 landed toolchain 0.5.0 / verification 0.3.0 mid-grace, so those two stack as 0.5.1 / 0.3.1; guardrails (0.9.2→0.9.3) and work-items (0.17.1→0.17.2) stack above their own mid-flight entries as before. All 13 manifests match their CHANGELOG top entry; songwriting's methodology-attribution note preserved. ## Related - #537 (wave 3 of 3 — closes) - #766 (superseded — pre-rebase head of this same change) - #755 / #758 (waves 1–2) - #426 (the two-plugin fix this mirrors) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Summary
/toolchain:setupstep 6 wrote.claude/topic-docs.yaml— a consumer config resolved by theimplementationandverificationplugins for artifact placement, not by any/toolchain:*skill.toolchainis a build/test/lint plugin that owns no lifecycle artifacts, so it was writing another plugin's consumer config. This relocates the offering to the lifecycle plugin that owns it, matching the established/discovery:setupand/planning:setuppattern (each lifecycle plugin's own setup offers the shared concern file, independent of whether the siblings are installed).verificationwas the actual gap: it is a fully-formed lifecycle plugin (it already shipsreference/topic-docs.mddescribing exactly what it writes per tier) but had no setup skill, so it depended ontoolchainto persist its config.planning/discoveryalready cover the sharedPLAN.md/EXPLORE.mdseam via their own setups.Fix
/verification:setup— settles the topic-docs seam for the consuming repo:check(default) reports the effective concern read-only;applypersists the tracked.claude/topic-docs.yaml(non-interactive from<key>=<value>args or a one-question interview) behind the committed-tiergit check-ignoreguard, never editing the consumer's root.gitignore. Mirrors/discovery:setup. Adds itsevals/evals.json./toolchain:setupto what it owns (the ecosystem command surface): removed the topic-docs report fromcheck, the offering fromapply(step 6), and the now-orphanedreference/topic-docs.mdbinding that only step 6 read.verification's Configuration/skill table now point to/verification:setup;toolchainno longer advertises the topic-docs offering).toolchain0.4.3 → 0.5.0 (capability removed) andverification0.2.4 → 0.3.0 (skill added), each with a top-inserted CHANGELOG entry.Verification
All commands run against
origin/mainin the worktree.node scripts/validate-plugin-contracts.mjs→Plugin contracts validated: 34 setup skills and 1824 plugin files checked.(was 33 setup skills)node scripts/generate-catalog.mjs --check→Catalog is in sync with the manifests.bash scripts/check-changelog-parity.sh --check→Every versioned plugin has a CHANGELOG.md ...bash scripts/check-skill-leaf-names.sh --check→All 8 cross-plugin skill leaf-name collisions are registered.(setupleaf is open by contract)bash scripts/check-changed-skills.sh origin/main→3 skill(s) checked, 0 failed.—verification/skills/setupandtoolchain/skills/setupboth PASS (0 errors).npx markdownlint-cli2on all 6 changed markdown files →Summary: 0 error(s).scripts/check-skill-portability.sh --allexits 1 on a pre-existingwork-items/trackbranch-default coupling, unrelated to this change; no new file is flagged.Closes #263
Related
plugins/discovery/skills/setupandplugins/planning/skills/setup.verification's per-artifact tier placement remains owned byplugins/verification/reference/topic-docs.md.🤖 Generated with Claude Code