Repository navigation
Commit 841ed38
fix(spec): six dist-reading gates answer an unmet build prerequisite with exit 3, not a finding's 1 (#19463)
Fixes #19227
Refs #19450
Clause-②: no
Six `packages/spec` gates refused an unmet **build** prerequisite with
`process.exit(1)` — the
code a real finding uses — while `scripts/import-prerequisite.mjs:250`
declares
`EXIT_PREREQUISITE_NOT_MET = 3` for exactly those two words and argues
the case in its own
docblock. This lands the six on that vocabulary. ⛔ Nothing about what a
real finding returns
moves: every `fail()`, `refuse()`, self-test, ratchet and diagnostics
verdict still exits 1.
## Why it is not cosmetic — reproduced in this round
`scripts/pm/dispatch-gates.mjs --ran` derives its NOT-MEASURED class
**from the recorded exit
code** (`dispatch-gates.mjs:13932`) and counts every other non-kill code
as a family that RAN.
Driven twice over the same derivation of this very branch, same tool,
same tree, only the six
recorded codes differing:
| the six recorded as | reconciliation |
|:---|:---|
| `exit 1` (before this PR) | `65 derived, 65 run, 0 NOT-MEASURED, 0
UNRUN` — and the tool calls it *"a DERIVED zero — all 65 recorded an
exit code and none of them is 3"* |
| `exit 3` (after this PR) | `65 derived, 59 run, 6 NOT-MEASURED, 0
UNRUN`, each of the six named with *"recorded exit 3 … PREREQUISITE NOT
MET"* |
So the card's sharpest claim — filed as UNREPRODUCED by both the filing
seat and the PM — holds:
a gate that refused before reading a single declaration was reconciled
as coverage the round did
not have. That is a reconciliation instrument reporting coverage it does
not have, not a code
mismatch.
## The true population — six gates, seven sites
The card verified four files with `grep -c 'process.exit(1)'` and could
not locate
`check-api-surface` / `check-api-surface-declarations` "under that
spelling". Measured here
against `origin/main` @ `8e368dc`, the population is the set of guarded
refusals reached through
`lib/dist-freshness.ts`:
| gate script | site | the card's reading |
|:---|:---|:---|
| `build-api-surface.ts` | stale/missing `dist` | **this is
`check:api-surface`** — spelled `build-*` because one file serves `gen:`
and `check:` |
| `check-browser-reachable-entries.ts` | stale/missing bundles | not in
the card at all; it already PRINTED `NOT MEASURED` and then exited 1 |
| `check-dual-source-exports.ts` | stale/missing `dist`, both modes |
`exit(1)` x6 |
| `check-entry-nameability.ts` | stale/missing `dist` | `exit(1)` x0 —
**the instrument was blind**: this gate `return`s its code to
`process.exit(main())` |
| `check-exported-any.ts` | stale/missing `dist` | `exit(1)` x5 |
| `check-skill-examples.ts` | stale `dist` **and** a self-package with
no declarations (was `fail()`) | `exit(1)` x6; the refusal text the card
could not find is at `check-skill-examples.ts:3219` |
`check-api-surface-declarations` does not exist as a separate gate under
any spelling. The nearest
candidate, `build-declaration-map.ts` (`check:declaration-map`), reads
no `dist` and has no
prerequisite refusal; `build-export-origins.ts` says in its own header
that it reads `src/`, never
the built dist. Recorded as: **not present**.
#19450 is the same defect measured independently on
`check-skill-examples.ts` (the refusal fires
when `packages/client-react/dist` holds no declarations; the built
closure returns a true exit 0).
Its site is covered here. ⛔ `Refs`, not `Fixes` — the dedupe/close call
is triage's.
## Dispositioned, not changed — with readings
- `check-entry-nameability.ts`'s dead-canary, foreign-diagnostic and
zero-probe refusals keep
`return 1`. The gate says so itself: *"Both are findings; neither is a
pass."*
- `check-skill-examples.ts`'s `refuse()` keeps exit 1 — a surface that
never reached tsc is the
gate's own invariant breaking, not an unbuilt workspace.
- Every `--self-test` failure, battery floor and verdict handshake keeps
exit 1: a broken detector
is a finding about the instrument.
- `check-dual-source-exports.ts`'s missing **tracked** baseline keeps
exit 1 — a checked-in file
that is absent is a repo-state finding, not a build-environment
prerequisite.
- `check-generated.ts:751` refuses a `readsDist` generator on a stale
dist, but folds it into
`failed` and exits `failed ? 1 : 0` across every sub-gate. There is no
per-gate exit to move
without changing what the aggregate returns for a real failure. Left
alone, recorded here.
## What the change is
`lib/dist-freshness.ts` is already this package's one home for the
precondition ("they live in ONE
home, this file, so the next bundle-reading gate finds them together"),
so it gains
`EXIT_PREREQUISITE_NOT_MET`, `EXIT_FINDINGS` and
`prerequisiteNotMetText()`; the seven call sites
use them. The verdict's own message — cause, damage, two-line build
remedy — is passed through
byte for byte; the wrapper adds the fleet phrase `GATE: PREREQUISITE NOT
MET — …` that
`check-dts-closure`, `check-dual-build-cjs-loads`, `check-i18n-bundles`,
`check-i18n-coverage` and
`check-closing-target-claim` all already print, plus the "Nothing was
measured" paragraph that
names the code. A number with no sentence beside it leaves the reader
where they were.
**Route (the brief offered both).** The shared
`scripts/import-prerequisite.mjs` **frame** is not
adopted: it is a dependency LOADER (`requireDependency` /
`requireDefaultExport`) answering "can
this gate import the package it names?", which is a different
prerequisite reached a different
way. The **constant** is hand-carried with the citation, because
`scripts/import-prerequisite.d.mts`
is partial by design — its own header records that the exit-code
constants are deliberately left
out — so importing the name is TS2305 until that root-tree mirror is
extended, and extending it is
outside this card's surface. Drift is closed by a pin on each side
instead: that module's
`--self-test` asserts `=== 3` there, and `dist-freshness.test.ts`
asserts the same here **and**
compares against the value read from that module itself.
## Verification
`origin/main` (`8f6d831`) is merged; it touched none of
`packages/spec/scripts/`,
`scripts/import-prerequisite.mjs` or `scripts/pm/dispatch-gates.mjs`.
Everything below is measured
**after** that merge, on `c28fe19`, with the closure rebuilt on the
merged sources (`turbo run
build` over spec + client + client-react, 34 tasks, exit 0) — each exit
captured before any pipe:
```
pnpm --filter @objectstack/spec run check:api-surface :: exit 0
pnpm --filter @objectstack/spec run check:browser-reachable-entries :: exit 0
pnpm --filter @objectstack/spec run check:dual-source-exports :: exit 0
pnpm --filter @objectstack/spec run check:entry-nameability :: exit 0
pnpm --filter @objectstack/spec run check:exported-any :: exit 0
pnpm --filter @objectstack/spec run check:skill-examples :: exit 0
pnpm --filter @objectstack/spec run check:generated :: exit 0
```
Six green is the positive control: the change refuses nothing CI is
legitimately in.
**Ablation.** The refusal in `check-exported-any.ts` was put back to
`console.error(freshness.message);
process.exit(1);` through `scripts/ablation-replace.mjs` (anchor hit x1,
blob
`8e3498ca72bf -> 391020853d3a` — the mutation is proved on disk, not by
an editor's exit code).
`dist-freshness-adoption.test.ts` then read **1 failed | 9 passed**, the
one failure being
`check:exported-any … AssertionError: expected 1 to be 3`. Nine cases
stayed green, so the pin is
targeted rather than blanket. Restored through the same tool: blob back
to `8e3498ca72bf`, equal to
HEAD, `git diff HEAD` empty. No `dist` preflight applies — these gates
run from source under `tsx`
and the sandbox copies `packages/spec/scripts`, which is precisely why
the mutation reached the run.
Tests and gates, all exit 0: `check:scripts-typecheck` ·
`@objectstack/spec typecheck` ·
`check:cross-package-test-inputs` · `check:nul-bytes` ·
`check:test-source-alias` ·
`check:issue-citations` · `check:pm-dispatch-gates`.
**Changeset: `skip-changeset`, measured.** `packages/spec`'s `files[]`
is
`dist json-schema liveness prompts llms.txt README.md src/**/*.zod.ts
CHANGELOG.md api-surface
spec-changes.json` — `scripts/` is not on it. After the build,
`prerequisiteNotMetText`,
`EXIT_PREREQUISITE_NOT_MET` and `inspectDistFreshness` each grep to
**0** files under those paths,
while the positive control (`QueryAST` 55, `ObjectSchema` 59) fires.
Nothing here publishes.
## Governed surfaces: none, and none falsified
The landing-path question, re-measured rather than inherited. The
instrument reaches governed prose
(control: 8 `exit` hits in `AGENTS.md`). Across `docs/adr/**`,
`docs/NORTH-STAR.md`, `.claude/**`,
`skills/**`, `AGENTS.md` and `CLAUDE.md`, **no file pins a number to
these gates' prerequisite
state.** The gate NAMES appear (`AGENTS.md:731,736,743`,
`.claude/skills/spec-property-retirement/SKILL.md:285,321-322`) and
carry no exit code.
`.claude/skills/pm-dispatch/references/lanes/` — the surface #14008 had
to repair — holds exactly
one `exit` mention today, `director.md:66`, about a different tool.
`AGENTS.md:736` ("a failure
there is a real finding to fix") reads MORE true once a prerequisite
stops being spelled as a
finding. ⇒ no governed hunk is pulled in, and this stays an ordinary
queue landing.
## Acceptance notes
Found while sweeping for the true population; ⛔ not fixed here, to be
filed rather than ridden in:
1. **`build-docs.ts:103-119` is a seventh site of the same class.** It
refuses a stale or missing
`json-schema` tree — a different artefact reached through a different
predicate
(`schemaTreeIsStale`, not `distIsStale`), outside the "six gates" this
card rules on — and it,
too, answers exit 1. Same remedy shape ("Generate it first"), same
reader confusion.
2. **Four unguarded `throw` backstops reach the shell as exit 1 with a
node stack trace** for the
same event: `build-api-surface.ts:145`, `check-exported-any.ts:143`,
`check-dual-source-exports.ts:125` ("Is the package built?") and
`check-entry-nameability.ts:311`
("Build first"). These are exceptions, not refusals with a chosen code,
so converting them is a
behaviour change rather than a constant swap — which is why they are
named here instead.
3. Noted, not filed: `AGENTS.md:735-737` calls `check:skill-examples`,
`check:exported-any` and
`check:dual-source-exports` "pure source audits", yet all three read the
built `dist` and refuse
on it. Pre-existing prose imprecision, untouched by this diff and
carried by no gate. Successor:
the next PR that edits that paragraph for another reason.
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
---
_Generated by [Claude
Code](https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent adabccf commit 841ed38
9 files changed
Lines changed: 305 additions & 34 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
64 | | - | |
| 64 | + | |
65 | 65 | | |
66 | 66 | | |
67 | 67 | | |
| |||
84 | 84 | | |
85 | 85 | | |
86 | 86 | | |
87 | | - | |
88 | | - | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
89 | 92 | | |
90 | 93 | | |
91 | 94 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
154 | 154 | | |
155 | 155 | | |
156 | 156 | | |
157 | | - | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
158 | 162 | | |
159 | 163 | | |
160 | 164 | | |
| |||
518 | 522 | | |
519 | 523 | | |
520 | 524 | | |
521 | | - | |
522 | | - | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
523 | 530 | | |
524 | 531 | | |
525 | 532 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
65 | 65 | | |
66 | 66 | | |
67 | 67 | | |
68 | | - | |
| 68 | + | |
69 | 69 | | |
70 | 70 | | |
71 | 71 | | |
| |||
396 | 396 | | |
397 | 397 | | |
398 | 398 | | |
399 | | - | |
400 | | - | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
401 | 409 | | |
402 | 410 | | |
403 | 411 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
163 | 163 | | |
164 | 164 | | |
165 | 165 | | |
166 | | - | |
| 166 | + | |
167 | 167 | | |
168 | 168 | | |
169 | 169 | | |
| |||
583 | 583 | | |
584 | 584 | | |
585 | 585 | | |
586 | | - | |
587 | | - | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
588 | 598 | | |
589 | 599 | | |
590 | 600 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
84 | 84 | | |
85 | 85 | | |
86 | 86 | | |
87 | | - | |
| 87 | + | |
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
| |||
447 | 447 | | |
448 | 448 | | |
449 | 449 | | |
450 | | - | |
451 | | - | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
452 | 455 | | |
453 | 456 | | |
454 | 457 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
297 | 297 | | |
298 | 298 | | |
299 | 299 | | |
300 | | - | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
301 | 306 | | |
302 | 307 | | |
303 | 308 | | |
| |||
1471 | 1476 | | |
1472 | 1477 | | |
1473 | 1478 | | |
| 1479 | + | |
| 1480 | + | |
| 1481 | + | |
| 1482 | + | |
| 1483 | + | |
| 1484 | + | |
| 1485 | + | |
| 1486 | + | |
| 1487 | + | |
| 1488 | + | |
| 1489 | + | |
| 1490 | + | |
| 1491 | + | |
| 1492 | + | |
| 1493 | + | |
| 1494 | + | |
| 1495 | + | |
| 1496 | + | |
| 1497 | + | |
| 1498 | + | |
| 1499 | + | |
| 1500 | + | |
| 1501 | + | |
| 1502 | + | |
1474 | 1503 | | |
1475 | 1504 | | |
1476 | 1505 | | |
| |||
3241 | 3270 | | |
3242 | 3271 | | |
3243 | 3272 | | |
3244 | | - | |
| 3273 | + | |
3245 | 3274 | | |
3246 | 3275 | | |
3247 | 3276 | | |
3248 | | - | |
| 3277 | + | |
3249 | 3278 | | |
3250 | 3279 | | |
3251 | 3280 | | |
3252 | | - | |
3253 | | - | |
3254 | | - | |
3255 | | - | |
| 3281 | + | |
| 3282 | + | |
3256 | 3283 | | |
3257 | 3284 | | |
3258 | 3285 | | |
| |||
3263 | 3290 | | |
3264 | 3291 | | |
3265 | 3292 | | |
3266 | | - | |
3267 | | - | |
3268 | | - | |
3269 | | - | |
3270 | | - | |
| 3293 | + | |
| 3294 | + | |
| 3295 | + | |
| 3296 | + | |
| 3297 | + | |
| 3298 | + | |
| 3299 | + | |
| 3300 | + | |
| 3301 | + | |
| 3302 | + | |
| 3303 | + | |
| 3304 | + | |
3271 | 3305 | | |
3272 | 3306 | | |
3273 | 3307 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| 46 | + | |
| 47 | + | |
46 | 48 | | |
47 | 49 | | |
48 | 50 | | |
| |||
181 | 183 | | |
182 | 184 | | |
183 | 185 | | |
184 | | - | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
185 | 196 | | |
186 | | - | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
187 | 200 | | |
188 | 201 | | |
189 | 202 | | |
| |||
245 | 258 | | |
246 | 259 | | |
247 | 260 | | |
248 | | - | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
249 | 264 | | |
250 | 265 | | |
251 | 266 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
34 | | - | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
35 | 41 | | |
36 | 42 | | |
37 | 43 | | |
| |||
470 | 476 | | |
471 | 477 | | |
472 | 478 | | |
473 | | - | |
| 479 | + | |
474 | 480 | | |
475 | 481 | | |
476 | 482 | | |
| |||
484 | 490 | | |
485 | 491 | | |
486 | 492 | | |
487 | | - | |
| 493 | + | |
488 | 494 | | |
489 | 495 | | |
490 | 496 | | |
| |||
495 | 501 | | |
496 | 502 | | |
497 | 503 | | |
498 | | - | |
| 504 | + | |
499 | 505 | | |
500 | 506 | | |
501 | 507 | | |
502 | 508 | | |
503 | 509 | | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
0 commit comments