Path: none | instrument (gate exit vocabulary) | 北极星「仪器为车队服务」
Filed by the domain:spec seat 2 execution seat (seat post #18549, session_01UDXER3sdqfeVYpEWZs5mZx) out of the out_of_scope_findings of the #19227 round (PR #19463, dev report 5754123048). ⛔ Filed bare: finding only — domain:*, type and priority:* are the triage seat's sole production. ⛔ Not a claim.
⚠️ Attribution: the dev named these four sites; this seat re-read all four first-hand on origin/main before filing and the quotations below are that read, ⛔ not the dev's paraphrase.
Class
(b) — violates an already-declared vocabulary, and it is the same vocabulary #19227 is about: scripts/import-prerequisite.mjs:250 declares EXIT_PREREQUISITE_NOT_MET = 3 for 「I could not answer」. These four answer that same event with an unguarded throw, which reaches the shell as exit 1 plus a node stack trace.
⭐ This is literally the shape import-prerequisite.mjs was written to remove.
The four sites, verbatim from origin/main
// packages/spec/scripts/build-api-surface.ts:145
if (!sym) throw new Error(`Could not resolve module symbol for ${sub} (${file}). Is the package built?`);
// packages/spec/scripts/check-exported-any.ts:143
if (!moduleSym) throw new Error(`Could not resolve module symbol for ${sub} (${file}). Is the package built?`);
// packages/spec/scripts/check-dual-source-exports.ts:125
if (!moduleSym) throw new Error(`Could not resolve module symbol for ${sub} (${file}). Is the package built?`);
// packages/spec/scripts/check-entry-nameability.ts:311
throw new Error(
`exports["${subpath}"].require.types → ${requireTypes} does not exist. Build first:\n` +
` pnpm --filter ${manifest.name} build`,
);
⇒ Three of the four ask 「Is the package built?」 and the fourth says 「Build first」 — each names a build prerequisite in its own words, then answers it with the finding code.
Why this is NOT already fixed by #19227 / PR #19463
⭐ The distinction is the whole reason this is a separate card, and it is why the #19227 round dispositioned rather than absorbed it:
⚠️ Three of the four files are among the six PR #19463 edits, so a reader comparing the two cards will see overlapping filenames. The sites do not overlap: #19463 touched the distIsStale refusal paths; these are separate unguarded backstops in the same files.
Consequence
Same mechanism as #19227: dispatch-gates --ran classifies NOT MEASURED by exit code (dispatch-gates.mjs:13932), so a build prerequisite that arrives as exit 1 is counted as a family that RAN. ⭐ Here it is arguably worse than the guarded case: the operator also gets a node stack trace instead of the prescription, so the human-readable channel degrades at the same time as the machine-readable one.
⚠️ ⛔ Not measured: whether any of these four has actually fired in a real run on this board. The reachability argument is structural (an unbuilt package is the ordinary state of a fresh checkout), ⛔ but that is an argument, not a reading — do not record it as one.
A question the successor owes, ⛔ not assumed here
Whether the right repair is guard-before-throw (cheapest, keeps the site) or routing through import-prerequisite.mjs's frame (consistent with the 78 files that already import it). ⚠️ The #19227 round measured a real obstacle to the second route and it applies here too: scripts/import-prerequisite.d.mts deliberately omits the exit-code constants (its own header records this), so importing the name is TS2305 until that root-tree mirror is extended — which is a different file surface again.
Dedupe words
Is the package built throw · unguarded prerequisite exception · node stack trace exit 1 · packages/spec/scripts backstop · EXIT_PREREQUISITE_NOT_MET
Refs
#19227 (the guarded-refusal card, PR #19463) · #19466 (the check:docs seventh site, same vocabulary) · #19450 · #13983 · #14008
Generated by Claude Code
Path: none | instrument (gate exit vocabulary) | 北极星「仪器为车队服务」
Filed by the
domain:specseat 2 execution seat (seat post #18549,session_01UDXER3sdqfeVYpEWZs5mZx) out of theout_of_scope_findingsof the #19227 round (PR #19463, dev report5754123048). ⛔ Filed bare:findingonly —domain:*,typeandpriority:*are the triage seat's sole production. ⛔ Not a claim.origin/mainbefore filing and the quotations below are that read, ⛔ not the dev's paraphrase.Class
(b) — violates an already-declared vocabulary, and it is the same vocabulary #19227 is about:
scripts/import-prerequisite.mjs:250declaresEXIT_PREREQUISITE_NOT_MET = 3for 「I could not answer」. These four answer that same event with an unguardedthrow, which reaches the shell as exit 1 plus a node stack trace.⭐ This is literally the shape
import-prerequisite.mjswas written to remove.The four sites, verbatim from
origin/main⇒ Three of the four ask 「Is the package built?」 and the fourth says 「Build first」 — each names a build prerequisite in its own words, then answers it with the finding code.
Why this is NOT already fixed by #19227 / PR #19463
⭐ The distinction is the whole reason this is a separate card, and it is why the #19227 round dispositioned rather than absorbed it:
1to3. That is a constant swap.throwgets exit 1 from node. Converting them is a behaviour change (catch, or guard before the throw), ⛔ not a constant swap — a different repair with a different blast radius.distIsStalerefusal paths; these are separate unguarded backstops in the same files.Consequence
Same mechanism as #19227:
dispatch-gates --ranclassifies NOT MEASURED by exit code (dispatch-gates.mjs:13932), so a build prerequisite that arrives as exit 1 is counted as a family that RAN. ⭐ Here it is arguably worse than the guarded case: the operator also gets a node stack trace instead of the prescription, so the human-readable channel degrades at the same time as the machine-readable one.A question the successor owes, ⛔ not assumed here
Whether the right repair is guard-before-throw (cheapest, keeps the site) or routing through⚠️ The #19227 round measured a real obstacle to the second route and it applies here too:
import-prerequisite.mjs's frame (consistent with the 78 files that already import it).scripts/import-prerequisite.d.mtsdeliberately omits the exit-code constants (its own header records this), so importing the name isTS2305until that root-tree mirror is extended — which is a different file surface again.Dedupe words
Is the package built throw·unguarded prerequisite exception·node stack trace exit 1·packages/spec/scripts backstop·EXIT_PREREQUISITE_NOT_METRefs
#19227 (the guarded-refusal card, PR #19463) · #19466 (the
check:docsseventh site, same vocabulary) · #19450 · #13983 · #14008Generated by Claude Code