Observed while re-deriving the local gate union for #12051 (PR #12308). Filed unassigned; not touched there — out of that card's scope.
The shape
node scripts/pm/dispatch-gates.mjs classifies pnpm --filter @objectstack/spec run check:skill-refs under "the layout MOVED under a gate that still spells the old path — a real miss, worth triaging", separately from the 11 families it calls unreachable by construction:
1 where THE LAYOUT MOVED under a gate that still spells the old path — a real miss, worth triaging:
- pnpm --filter @objectstack/spec run check:skill-refs [lint.yml]
dead: 'lib/file-description' — no tracked path under its first segment; never was a repo path
· 'lib/generated-output' — no tracked path under its first segment; never was a repo path
· '@objectstack/spec' — no tracked path under its first segment; never was a repo path · …
Every literal the derivation can recover from that gate's source is an import specifier, not a path — lib/… relative imports and the package's own name. So no change to any card's file list can make the derivation name this gate, and it scores the same quiet green for every card in the tree, skills/** cards included. That matters more than usual here: check:skill-refs is the gate that keeps skill cross-references honest, and skills/** is a governed surface, so the gate most likely to be relevant to a skills card is the one a dispatch can never name for it.
To be clear about what this is and is not: CI runs check:skill-refs on every pull request (it sits in lint.yml with no paths filter), so nothing is unguarded today. What is missing is the dispatch-time naming — the derivation's job is to tell a dev which gates to run locally, and for this one it structurally cannot.
Why the classification itself may be the more interesting half
The three dead literals look like the same import-specifier shape as several of the 11 the same run files under "unreachable BY CONSTRUCTION" (check:api-surface's lib/dist-freshness, check:exported-any's lib/dist-freshness, …). If they really are the same shape, then either this one is misfiled as remediable or those are misfiled as hopeless — the two buckets carry opposite prescriptions ("triage this" vs "no change reaches it"), so whichever way it resolves, one of them is telling a reader the wrong thing. That is a question about the classifier, not about check:skill-refs, and it is worth answering before anyone acts on either bucket.
Prior art
This class has been closed repeatedly by teaching the gate to declare a reachable population: #10790 (check:parse-guard, literal scripts refused as too generic), #10314 (check:examples-live-imports, bare examples), #9626 (check:doc-anchors, root 'content' not "pathy"), #9955 (check:test-source-alias). The remedy shape is established; what is not established is whether it applies here, per the paragraph above.
Repro
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack <any changed path># read the "Unreachable" section
Measured on objectstack-ai/objectstack at 516420e.
Generated by Claude Code
Observed while re-deriving the local gate union for #12051 (PR #12308). Filed unassigned; not touched there — out of that card's scope.
The shape
node scripts/pm/dispatch-gates.mjsclassifiespnpm --filter @objectstack/spec run check:skill-refsunder "the layout MOVED under a gate that still spells the old path — a real miss, worth triaging", separately from the 11 families it calls unreachable by construction:Every literal the derivation can recover from that gate's source is an import specifier, not a path —
lib/…relative imports and the package's own name. So no change to any card's file list can make the derivation name this gate, and it scores the same quiet green for every card in the tree,skills/**cards included. That matters more than usual here:check:skill-refsis the gate that keeps skill cross-references honest, andskills/**is a governed surface, so the gate most likely to be relevant to a skills card is the one a dispatch can never name for it.To be clear about what this is and is not: CI runs
check:skill-refson every pull request (it sits inlint.ymlwith no paths filter), so nothing is unguarded today. What is missing is the dispatch-time naming — the derivation's job is to tell a dev which gates to run locally, and for this one it structurally cannot.Why the classification itself may be the more interesting half
The three dead literals look like the same import-specifier shape as several of the 11 the same run files under "unreachable BY CONSTRUCTION" (
check:api-surface'slib/dist-freshness,check:exported-any'slib/dist-freshness, …). If they really are the same shape, then either this one is misfiled as remediable or those are misfiled as hopeless — the two buckets carry opposite prescriptions ("triage this" vs "no change reaches it"), so whichever way it resolves, one of them is telling a reader the wrong thing. That is a question about the classifier, not aboutcheck:skill-refs, and it is worth answering before anyone acts on either bucket.Prior art
This class has been closed repeatedly by teaching the gate to declare a reachable population: #10790 (
check:parse-guard, literalscriptsrefused as too generic), #10314 (check:examples-live-imports, bareexamples), #9626 (check:doc-anchors, root'content'not "pathy"), #9955 (check:test-source-alias). The remedy shape is established; what is not established is whether it applies here, per the paragraph above.Repro
Measured on
objectstack-ai/objectstackat516420e.Generated by Claude Code