Skip to content

[finding] check:skill-refs can never be path-named — its declared population is three import specifiers, none of which is a repo path #12310

Description

@os-litant

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

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions