Repository navigation
Commit 62d830e
fix(scripts): teardown-shape self-test refuses an unreachable pinned control as PREREQUISITE NOT MET (exit 3) (#18644)
Fixes #18217
Clause-②: no — a gate's exit register is not a published contract face,
and nothing under any package's `files[]` moves. Re-judged from the
actual diff, measured below.
## What moved, and what deliberately did not
`node scripts/check-plugin-teardown-shape.mjs --self-test` exited **1**
— the code reserved for a tree that is genuinely wrong — when a shallow
clone could not reach the commit its positive control is pinned to. The
true condition is PREREQUISITE NOT MET, which this tree already answers
with exit **3**.
One file, three lines of behaviour:
1. The unreachable-control refusal returns `EXIT_PREREQUISITE_NOT_MET`
instead of `1`.
2. The entry point's verdict handshake flattened **every** early return
to 1, so a deliberately chosen code could not have survived it. It now
preserves the prerequisite code alone; every other early return —
including a bare `return`, which arrives as `undefined` and whose
`process.exit(undefined)` is the exit-0 hole that handshake exists to
close — is still 1.
3. A one-line note beside the pin says why this code differs from the
failure code.
⛔ The refusal itself is unchanged: it fires where it fired, and its text
— which already names `git fetch --unshallow origin main` — is
byte-identical. Only the code moved. A self-test that RAN and genuinely
failed still exits 1.
### Import or respell: measured on this tree, then followed
Both spellings of the constant exist under `scripts/`. **Imported** by
check-dts-closure, check-i18n-bundles, check-i18n-coverage,
check-i18n-walk-parity, check-sourcemap-no-sources-content,
check-vendor-export-contract, ci/select-shard-timings-run,
pm/check-dispatch-gates, pm/check-governed-merges and pm/dispatch-gates
— the gate the card names as owning this code. **Re-declared locally**
by check-test-completeness, check-release-section-coverage,
pm/changeset-deadline-census, pm/check-half-states,
pm/check-prior-rulings and pm/check-settings-deny-roster — each one a
script that does not otherwise depend on that frame.
This gate already imports `scripts/import-prerequisite.mjs`
(`requireDefaultExport`), so importing the constant from it adds no
dependency edge and leaves the number declared once, in the module that
argues it. Taken: **import**.
## Acceptance, both directions, on a REAL shallow clone
Not faked by editing the pin to a nonexistent sha. A throwaway `git
clone --depth 1 file://…` of this branch's base: `git rev-parse
--is-shallow-repository` reads `true`, `git cat-file -e
621a487` exits 1 (the object is
genuinely absent), and `node_modules` is symlinked in so the
import-prerequisite guard is not the thing being measured.
| leg (same clone, same rev) | script under test | exit |
|---|---|---|
| unreachable pinned control | `origin/main` @ 25c9a83 | **1** |
| unreachable pinned control | this branch | **3** |
`diff` over both runs' stdout **and** stderr is empty: the refusal text,
remedy line included, is byte-identical.
| leg | reading |
|---|---|
| reachable control, this branch | exit 0, 48 cases pass |
| reachable control, `origin/main` @ 25c9a83 | exit 0, 47 cases pass |
| injected genuine failure (`preFixResult.findings.length === 1` flipped
to `=== 2`) | exit **1**, `1 of 48 case(s) failed` — not 3 |
| production leg (no `--self-test`), both trees | exit 0, verdict line
byte-identical |
The pass line is byte-identical except its case COUNT, which went
**up**, 47 to 48: the added case is this behaviour's pin. That battery's
floor moves 1 to 2 with it, so deleting the case reds instead of
silently shrinking the battery. Nothing goes down.
### The added case
The self-test spawns itself under a `git` that resolves nothing (a stub
first on `PATH`, exiting 128). The branch taken is the same `show.status
!== 0` the real shallow clone takes; what is pinned is the exit code
together with the remedy text. Out of process deliberately — the code is
only observable at the dispatch, and an in-process call would read a
number the entry point could still flatten.
## Ablation ledger
Every leg through `scripts/ablation-replace.mjs` (anchor must hit,
before/after counts, blob hashes, proven restore, EXIT/INT/TERM trap).
Each restore printed `blob == HEAD (e4d9e35)` and an empty `git
diff HEAD`.
| mutation | prediction | observed |
|---|---|---|
| `return EXIT_PREREQUISITE_NOT_MET;` to `return 1;` | the new pin reds
| `1 of 48 case(s) failed`, exit 1 — the case reports the child status
as 1 |
| dispatch `selfTestCode === EXIT_PREREQUISITE_NOT_MET ? … : 1` to
`process.exit(1);` | the new pin reds | `1 of 48 case(s) failed`, exit 1
|
| `preFixResult.findings.length === 1` to `=== 2` (a self-test that RAN
and failed) | exit 1, never 3 | exit **1**, `1 of 48 case(s) failed` |
| `const SELF = fileURLToPath(import.meta.url);` to `return;` (the
hole-2 handshake probe) | handshake holds: paragraph printed, exit 1,
never 0 | exit **1**, paragraph printed |
## Gates
Derived at 19cae6e with `node scripts/pm/dispatch-gates.mjs --commands
--repo objectstack-ai/objectstack`: **30 commands**, every one run, each
exit code recorded, then reconciled:
```
✓ dispatch-gates --ran: 30 derived famil(ies) accounted for — 30 run, 0 NOT-MEASURED
(a DERIVED zero — all 30 recorded an exit code and none of them is 3).
```
All 30 recorded `exit 0`. `check:pm-dispatch-gates` was detached and
waited on by recorded PID with `tail --pid`, 818.5s on this box; its
`exit 0` is read from two facts rather than claimed — the `&&` chain
advanced past the first leg (so that leg exited 0), and the second leg
was then re-run standalone with its status captured before any pipe
(`exit=0`, 812.2s, 1746 cases pass).
## Changeset
`skip-changeset`, measured rather than assumed: the diff's only path is
judged against every non-private manifest's `files[]` (70 manifests; the
repo root is `private`). `scripts/check-plugin-teardown-shape.mjs` lies
under no package directory, so nothing published moves. Firing control
on the same probe: `packages/lint/CHANGELOG.md` reads PUBLISHED via
`@objectstack/lint` `files[] "CHANGELOG.md"`.
## Acceptance notes
- `node scripts/measure-self-test-floor.mjs --probe --only
scripts/check-plugin-teardown-shape.mjs` refuses on this tree (its
handshake recogniser and the landed spellings disagree about three
unrelated files) — so the handshake column is NOT MEASURED by that
instrument here. Control: the refusal is byte-identical on `origin/main`
@ 25c9a83, so it pre-exists this change. The handshake is instead
proven directly by the fourth ablation leg above. Reported to the
dispatching seat as a candidate card; not filed from here.
- `lint.yml`'s step comment for this gate says "one `git show` and two
spawns"; the added case makes it three. Not edited: this card's declared
file surface is `scripts/`. Noted, not filed.
---
_Generated by [Claude
Code](https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent d6137fd commit 62d830e
1 file changed
Lines changed: 36 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
141 | 141 | | |
142 | 142 | | |
143 | 143 | | |
144 | | - | |
| 144 | + | |
145 | 145 | | |
146 | 146 | | |
147 | | - | |
| 147 | + | |
148 | 148 | | |
149 | 149 | | |
150 | 150 | | |
| |||
175 | 175 | | |
176 | 176 | | |
177 | 177 | | |
178 | | - | |
| 178 | + | |
179 | 179 | | |
180 | 180 | | |
181 | 181 | | |
| |||
334 | 334 | | |
335 | 335 | | |
336 | 336 | | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
337 | 341 | | |
338 | 342 | | |
339 | 343 | | |
| |||
702 | 706 | | |
703 | 707 | | |
704 | 708 | | |
705 | | - | |
| 709 | + | |
706 | 710 | | |
707 | 711 | | |
708 | 712 | | |
| |||
715 | 719 | | |
716 | 720 | | |
717 | 721 | | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
718 | 744 | | |
719 | 745 | | |
720 | 746 | | |
| |||
920 | 946 | | |
921 | 947 | | |
922 | 948 | | |
923 | | - | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
924 | 955 | | |
925 | 956 | | |
926 | 957 | | |
| |||
0 commit comments