docs(decisions): 0255 — skill namespaces keep v1 and fabrika apart (#4829) - #5277
Conversation
No preview deploy
|
|
review-doc: advisory — blocking-set PR (§CP — approval-gated) Verified fresh against issue #4829's acceptance criteria, read-only from the PR head via a per-run ref. Reviewed-head: @ 951a1fb §CP classification: control-plane, decided on the content axis, not the path axis. Class fan: Acceptance criteria
Grounding check — the premise-is-false claim, verified against the shipped CLIThe ADR's whole branch-2 conclusion rests on "the premise is false: v1 and fabrika are never invoked
The live setup also corroborates the ADR's framing independently of the PR: Advisory (non-blocking) — one citation in §"What was measured" is mis-scopedMeasurement 1 says "the frontmatter validator rejects a non-plugin skill whose This does not falsify the finding — the skill-side guarantee is real, it is just a different and Second, smaller note: the shipped skill frontmatter carries an ADR numbering — renumber verified clean at this head
Hygiene
Verified read-only from a per-run ref at |
|
review-skill: advisory — blocking-set PR (§CP — approval-gated) Behavioral-artifact gate over the two changed fabrika contracts. Verified read-only from the PR head Reviewed-head: @ 951a1fb §CP classification: control-plane by content, not path. CODEOWNERS (read live from Why this gate is required: Scope of this gateTwo files, both
Ruling on the disclosed class-7 deviation — the
|
…namespaces (#4829) Settles #4829. Measured, not assumed: the CLI namespaces plugin skills as `<plugin>:<skill>` and refuses a colon in any other skill's name, and a live phoenix session's roster carries both the bare v1 set and the `fabrika:*` set. So the bare name is unambiguously v1's and there is no name collision to cut the `.claude/skills` symlink over — what overlaps is the description, which is what a model invokes off. Takes the issue's branch 2: keep the loading path, correct the record, name the retirement lever. v1 retires as a set when `.claude/skills` and `.claude/agents` are deleted alongside the ADR 0077 suppression, in one change. Covers `.claude/agents` (same lever, no collision — fabrika ships no agents) and confirms `.claude/.pipeline` is unaffected. Reconciles the "dormant only by configuration" paragraph in the fabrika report contract and sharpens the triage contract's already-correct correction. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three in-flight lanes each derived 0253 off the same origin/main max (0252). Ordered by PR creation time, #5271 (04:18:29Z) keeps 0253, #5273 (04:18:57Z) takes 0254, and this PR (04:25:21Z) takes 0255. Renames the file, updates the frontmatter `id` and the H1 self-reference, and repoints the two fabrika contract links. No decision content changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…th, not the skill validator The reviewer's non-blocking advisory on PR #5277: measurement 1 cited "names must not contain ':' (reserved for plugin namespacing)" as the SKILL frontmatter validator's message. The string is real and verbatim in the shipped CLI (2.1.226), but it occurs at exactly two sites and both are on the AGENT path — parseAgentFromMarkdown and the agent parse-error helper. There is no skill-side occurrence, so the sentence sent a future auditor hunting a rule that isn't there. Re-grounded on the two skill-side strings verified first-party against the same shipped binary: the Skill tool's instruction text ("Plugin skills use `plugin:skill`.") and the skill-name validator ("Skill names match the skill's directory name (or 'plugin:skill' for plugin-qualified skills)"). The conclusion, the §1 naming rule, and the branch-2 decision are unchanged. Also softened "no bare name is ever contested" by one clause: the shipped opt-in `fallback` frontmatter field lets a bare-named skill yield to a same-suffix plugin skill. No skill in this repo declares it, so the conclusion stands. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
951a1fb to
c6fb167
Compare
|
review-doc: advisory — blocking-set PR (§CP — approval-gated) Re-review at the new head after repair round 1. The prior verdicts (bound to Reviewed-head: @ c6fb167 §CP classification — re-derived on BOTH axes at this head. Control plane, decided on the Class fan — re-run at this head, not reused. Acceptance criteria (#4829)
Grounding — is the CORRECTED attribution actually TRUE at source?The whole point of the repair was factual accuracy, so I re-grounded every claim in the rewritten
Also re-verified, for the softening clause: the
Advisory (non-blocking, no action required) — one residual imprecisionThe rewritten sentence says the colon spelling "is reserved for the plugin-qualified form." The ADR numbering + dangling-reference check, re-run at this head
Doc hygiene
CIAll checks green at this head — 23 success, 7 skipped, 0 failures. Verified read-only from a per-run ref at |
|
review-skill: advisory — blocking-set PR (§CP — approval-gated) Re-review at the new head after repair round 1. The prior Reviewed-head: @ c6fb167 §CP classification — re-derived on BOTH axes at this head. Control plane by content, not by Why this gate is required. What actually changed since the reviewed headThe repair round touched only Skill-rigor checklist
Specialist fan-out (skill-class dimensions)Ran over the changed contract text at this head: no unreachable step, no contradictory Hygiene
Verified read-only from a per-run ref at |
The repo carries two skill sets right now — the old pipeline (v1) and its fabrika rebuild — and a
worry had been recorded that a rebuilt skill and its v1 original were fighting over the same name.
They are not. I measured it: Claude Code names a plugin's skills
plugin:skill, and a plain skill'sname is just its directory name — so the plain
reportis always v1's and the rebuild is only everfabrika:report. Both show up in a real session, side by side, under different names.That changes the answer. There is no name fight to fix, so this PR keeps the current setup, writes
down the rule (plain name means v1,
fabrika:means the rebuild), and names the single edit thatretires the whole old set later. What does genuinely overlap is the descriptions — which is what
the model actually picks a skill by — and that was already the recorded mitigation.
Fixes #4829
What this changes
0255(.decisions/0255-skill-namespaces-keep-v1-and-fabrika-apart.md) — takes theissue's branch 2 (keep the loading path, correct the record), states the namespace rule, explains
why the symlink is not cut now, and sequences the cutover.
claude-plugins/fabrika/skills/report/contract.md— the "dormant only by configuration"paragraph is corrected in place and points at the ADR.
claude-plugins/fabrika/skills/triage/contract.md— its already-correct correction issharpened to say the overlap is in the description, not the name, and cites the ADR instead of the
open issue.
Acceptance criteria
path is not cut now) and §3 (the three-step sequence, ending in one edit that deletes both
symlinks and removes the ADR 0077 suppression together).
.claude/agentsand states whether.claude/.pipelineis affected.§4 covers
.claude/agents— same mechanism, same lever, and no collision today because fabrikaships no agent definitions. §5 confirms triage's read:
.claude/.pipelineis a path alias, nota roster-load directory, so it is unaffected. §5 adds the qualifier the write-code skill scripts are unreachable in an agent worktree — .claude/.pipeline symlink is not provisioned (exit 127 on the Step-4 preflight) #4818 precedent needed —
tracking a symlink is safe for a path alias and is a roster decision for a load path.
reportcontract's paragraph is reconciled. Corrected in place with a pointer to theADR.
both against Claude Code 2.1.226 and both recorded in the ADR's Context: the Skill tool's own
instruction text ("Plugin skills use
plugin:skill.") plus the skill-name validator("Skill names match the skill's directory name (or 'plugin:skill' for plugin-qualified
skills)"), and a live phoenix session's roster carrying bare
adr/report/triagealongside
fabrika:adr/fabrika:report/fabrika:triage.DEVELOPMENT.md pins 13 skill references to .claude/skills paths, so they resolve to v1 only #5275 (
DEVELOPMENT.md's 13 path pins, which neither CLAUDE.md pins skill routing to a filesystem path, so a fabrika skill can never inherit routing #4761 nor The crew reaches its skills by hardcoded path, so the fabrika cutover is a 22-site path rewrite with no ticket #4762 scopes). Both named inthe ADR's Records.
Notes for review
adr,plan-epic,report,triage.only adds the measured detail that the plugin toggle's scope was always the plugin copy, never the
symlink, which is what 0077 intended.
claude-plugins/kampus-pipeline/file is touched; v1 stays the frozen baseline (ADR 0238).pnpm lint:worktreeis a clean skip (no biome-handled files changed);pnpm typecheckpasses across all 31 workspace tasks.precedent).
0255, not0253. Three in-flight lanes each derived0253off the sameorigin/mainmax (0252). Ordered by PR creation time, docs(decisions): 0253 — the eval record is aneval-namespaced PR comment (#4769) #5271 keeps0253, docs(decisions): 0254 — the ready-for: gap closes lazily at triage time, never by backfill (#5041) #5273 takes0254,and this PR takes
0255.pipeline-cli decisions-index validatepasses.Deviations
reconcile,
claude-plugins/fabrika/skills/report/contract.md. Did: also editedclaude-plugins/fabrika/skills/triage/contract.md(two sentences). Why: that file had alreadyindependently falsified the
reportcontract's premise and cited this issue as the open question;leaving it citing an open issue after the issue is settled, and leaving its "the stated mitigation
is inert" line standing when the ADR concludes the mitigation is the right one, would put the
corpus at odds with the ADR the same PR lands. Disposition: for the reviewer to judge — the
edit is confined to the paragraph that names The .claude/skills symlink loads v1 skills regardless of the plugin toggle, so v1 and fabrika skills are model-invoked under one name today #4829 and adds no new claim beyond the ADR's.
current-head gate FAIL. Did: pushed a round while both namespaces stood at PASS/advisory,
which staleness-invalidates the markers bound to
951a1fb. Why: thereview-docverdictrecorded a non-blocking advisory that measurement 1 attributed the message "names must not
contain ':' (reserved for plugin namespacing)" to the skill frontmatter validator, when both
of its two occurrences in the shipped CLI are on the agent path (
parseAgentFromMarkdownandthe agent parse-error helper). An ADR that lands carrying a wrong attribution is far more
expensive to correct later than now, and the PR is §CP and not yet approved. Disposition: the
new head needs a fresh
review-doc+review-skillpass before approval.advisory suggested a one-sentence swap of the cited mechanism. Did: that swap, re-grounded on
two skill-side strings re-verified first-party against the same binary, plus the reviewer's
second, optional note — softened "no bare name is ever contested" by one clause naming the
shipped opt-in
fallbackfrontmatter field. Why: thefallbackqualifier cost one clause andno skill in this repo declares it, so the conclusion is untouched. Disposition: the ADR's
conclusion, §1 naming rule, branch-2 decision and Banned list are unchanged; the branch was also
rebased onto latest
origin/main(clean).