Filed unassigned and ungraded, observation-class, severity not judged. Found while working #12529 (an unrelated comment repair in packages/cli), so it is filed on its own card rather than folded into that PR.
Measured
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, run on 52a982388, prints an Unreachable section headed:
9 where THE LAYOUT MOVED under a gate that still spells the old path — a real miss, worth triaging
with entries such as:
- pnpm --filter @objectstack/spec run check:spec-changes [lint.yml]
dead: 'packages/spec/src/kernel/protocol-version' — the tree stops at
packages/spec/src/kernel; the layout moved under it · …
The layout did not move. Those literals are extensionless module specifiers, and the files are tracked — checked with git ls-files "$p" "$p.ts" "$p.mts" "$p.mjs" "$p.js" "$p.tsx" for each:
| literal reported dead | actually tracked as |
|---|
packages/spec/scripts/lib/dist-freshness | …/dist-freshness.ts |
packages/spec/scripts/lib/sharded-artifacts | …/sharded-artifacts.ts |
packages/spec/scripts/lib/export-origins-layout | …/export-origins-layout.ts |
packages/spec/scripts/lib/strictness-ledger | …/strictness-ledger.ts |
packages/spec/scripts/lib/strictness-ledger-doc | …/strictness-ledger-doc.ts |
packages/spec/src/kernel/metadata-plugin.zod | …/metadata-plugin.zod.ts |
packages/spec/src/kernel/protocol-version | …/protocol-version.ts |
packages/spec/src/migrations/registry | …/registry.ts |
packages/spec/src/migrations/spec-changes | …/spec-changes.ts |
packages/spec/src/conversions/registry | …/registry.ts |
packages/spec/src/meta-spelling/manifest-collection-spelling | …/manifest-collection-spelling.ts |
packages/spec/src/meta-spelling/metadata-url-spelling | …/metadata-url-spelling.ts |
12 of the 14 literals in that section resolve to a tracked .ts file. The two that genuinely do not resolve are not "moved layout" either: packages/spec/scripts/dist/other.d.ts is build output and packages/node_modules/typescript/bin/tsc is an installed binary.
Demonstrated in one run
Passing one of those very files to the script makes both halves visible at once:
$ node scripts/pm/dispatch-gates.mjs --residue packages/spec/src/migrations/registry.ts
- …check:spec-changes [lint.yml] names: packages/spec/src/kernel/protocol-version,
packages/spec/src/migrations/registry, packages/spec/src/migrations/spec-changes, …
- …check:spec-changes [lint.yml] dead: 'packages/spec/src/migrations/registry'
— the tree stops at packages/spec/src/migrations; the layout moved under it · …
The family names the path, the path exists, and the same run still classifies it dead.
Two consequences, and the second is the expensive one
It manufactures triage work. The heading calls it "a real miss, worth triaging", so a reader is sent after nine defects that do not exist.
⭐ In the opposite direction, and worse: because the literals are classified unreachable, the nine families declaring them can never be matched to a change set. A dev editing packages/spec/src/migrations/registry.ts does not get check:spec-changes in their derived local gate list — it lands in the unreachable bucket instead of the matched one. By the script's own words an unreachable family "score[s] the same quiet green for every card in the tree", which is precisely the outcome a local-gate derivation exists to prevent. The under-derivation is silent and the script exits 0.
Families affected
All packages/spec, all in lint.yml except the last, which is in spec-liveness-check.yml: check:api-surface, check:dual-source-exports, check:entry-nameability, check:export-origins, check:exported-any, check:meta-url-spelling, check:spec-changes, check:upgrade-guide, check:strictness-ledger.
Direction, not a decision
The path matcher probably needs to try the module-resolution extensions when a literal carries none, before concluding a prefix is dead. ⛔ Unverified — the matcher itself was not read, only its output.
Dedup
Semantic issue search for this returned zero. That zero was reverse-checked with a query in the same instrument that does return results (#12529 and #11958), so it is a real zero rather than a broken search.
Generated by Claude Code
Filed unassigned and ungraded, observation-class, severity not judged. Found while working #12529 (an unrelated comment repair in
packages/cli), so it is filed on its own card rather than folded into that PR.Measured
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, run on52a982388, prints an Unreachable section headed:with entries such as:
The layout did not move. Those literals are extensionless module specifiers, and the files are tracked — checked with
git ls-files "$p" "$p.ts" "$p.mts" "$p.mjs" "$p.js" "$p.tsx"for each:packages/spec/scripts/lib/dist-freshness…/dist-freshness.tspackages/spec/scripts/lib/sharded-artifacts…/sharded-artifacts.tspackages/spec/scripts/lib/export-origins-layout…/export-origins-layout.tspackages/spec/scripts/lib/strictness-ledger…/strictness-ledger.tspackages/spec/scripts/lib/strictness-ledger-doc…/strictness-ledger-doc.tspackages/spec/src/kernel/metadata-plugin.zod…/metadata-plugin.zod.tspackages/spec/src/kernel/protocol-version…/protocol-version.tspackages/spec/src/migrations/registry…/registry.tspackages/spec/src/migrations/spec-changes…/spec-changes.tspackages/spec/src/conversions/registry…/registry.tspackages/spec/src/meta-spelling/manifest-collection-spelling…/manifest-collection-spelling.tspackages/spec/src/meta-spelling/metadata-url-spelling…/metadata-url-spelling.ts12 of the 14 literals in that section resolve to a tracked
.tsfile. The two that genuinely do not resolve are not "moved layout" either:packages/spec/scripts/dist/other.d.tsis build output andpackages/node_modules/typescript/bin/tscis an installed binary.Demonstrated in one run
Passing one of those very files to the script makes both halves visible at once:
The family names the path, the path exists, and the same run still classifies it dead.
Two consequences, and the second is the expensive one
It manufactures triage work. The heading calls it "a real miss, worth triaging", so a reader is sent after nine defects that do not exist.
⭐ In the opposite direction, and worse: because the literals are classified unreachable, the nine families declaring them can never be matched to a change set. A dev editing
packages/spec/src/migrations/registry.tsdoes not getcheck:spec-changesin their derived local gate list — it lands in the unreachable bucket instead of the matched one. By the script's own words an unreachable family "score[s] the same quiet green for every card in the tree", which is precisely the outcome a local-gate derivation exists to prevent. The under-derivation is silent and the script exits 0.Families affected
All
packages/spec, all inlint.ymlexcept the last, which is inspec-liveness-check.yml:check:api-surface,check:dual-source-exports,check:entry-nameability,check:export-origins,check:exported-any,check:meta-url-spelling,check:spec-changes,check:upgrade-guide,check:strictness-ledger.Direction, not a decision
The path matcher probably needs to try the module-resolution extensions when a literal carries none, before concluding a prefix is dead. ⛔ Unverified — the matcher itself was not read, only its output.
Dedup
Semantic issue search for this returned zero. That zero was reverse-checked with a query in the same instrument that does return results (#12529 and #11958), so it is a real zero rather than a broken search.
Generated by Claude Code