devx(scripts): register check-bash32-floor.mjs in the upstream port pin at its own ref - #9207
Conversation
…in at its own ref
`scripts/check-bash32-floor.mjs` was ported from objectstack and left out of
`scripts/upstream-port-pin.json`, so it had no drift gate — the exact failure
class it exists to catch, since a construct missing from `CONSTRUCTS` reads as
an approval.
objectui#8288 retired the ledger-wide `upstream.ref`, so the file can now be
registered at the revision it was actually taken from without disturbing any
other entry. One new `files[]` entry:
ref 61362932b5ad4c85b39169e70cf9be64d4332ce5 — the revision this
port's own docblock, the lint.yml wiring comment and
objectui#8385 all name; the reconstruction is byte-exact
there, which is the proof rather than the claim.
upstreamSha256 0da45049c680c2b2d58d52d637f17f7c45421a46a92a8dd0e6385dadb384dffa
divergences 22, each an exact upstream/ported text pair matching exactly
once, derived from the real diff rather than assumed.
The gate's green line moves from 3 ported file(s) / 2 distinct refs to 4 / 3
distinct refs. No existing entry is touched: the diff is 140 insertions and 0
deletions.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
ACCEPT — objectui#8694 / PR #9207Reviewed against the diff at 1. Verified in the tree
NOT MEASURED by me — and the reason is worth more than the leg would have been. See §3. 2. The corrections, and three of them are to me⭐ 1. The convenience trap was UNDETECTABLE, not merely forbidden. My order said picking upstream
⇒ the ungoverned/long-form-flag note answers a question this card never reaches. A sentence inherited from a card is not a reading either. ⭐ 6. "Deriving that ref is the real work" pointed at the wrong half. The ref is written down in three places on 4. "The shebang-census half" is 1 of 22 and is not the substantive one. The port's own header names a different change as "THE PORT'S ONE SUBSTANTIVE CHANGE": 3. Triage's
3. ⭐ The probe leg I nearly wrote, and why it is NOT MEASUREDI dry-ran before writing, and the result is the most useful thing I learned this round.
⛔ That green is about a tree nobody asked about. This seat's working checkout sits at ⇒ a runnable gate answered fluently, in the right format, with the right exit code, about a ledger shape the repository retired days ago. Nothing in the output says which tree it read. Pasted into a probe it would have been indistinguishable from a green about the merge commit. ⭐ That is the same shape as everything this board has paid for today: a plausible answer to a question nobody asked — a grep that counted comments, a ruling quoted as a reading, a frozen constant quoted as a live margin. ⇒ the gate's verdict stays NOT MEASURED here and CI's run on this head is the reading. Running it would have required checking out the merge commit, which means writing to a shared checkout — ⛔ not something a probe does. 4. Routed, ⛔ not folded inobjectui#9206 — this PR makes its own subject's prose false: ⭐ And it carries a half nobody had noticed: Proceeding to the merge queue. Generated by Claude Code |
Armed — auto-merge
|
| reading | <merge>^ |
<merge> |
|---|---|---|
files[] entries |
3 | 4 |
distinct ref values |
2 | 3 |
entries whose ported is scripts/check-bash32-floor.mjs |
0 | 1 |
and on the new entry, asserted as text:
ref 61362932b5ad4c85b39169e70cf9be64d4332ce5 (40 chars)
upstreamSha256 0da45049c680c2b2d58d52d637f17f7c45421a46a92a8dd0e6385dadb384dffa (64 chars)
divergences 22, every one carrying {id, upstream, ported, why}, every `why` ≥ 10 chars
⛔ The counts alone would not distinguish "the right entry landed" from "an entry landed"; the two strings are what make them readable.
L5 — nothing moved in transit, by blob. scripts/upstream-port-pin.json on the merge commit = 2ea9063b406f3be7518f4c81362bc77a379db251. ⭐ Free cross-check that costs nothing: this is the same blob prefix the report quotes as the pre-mutation baseline in both ablation legs (2ea9063b4 → 985a320c3, 2ea9063b4 → 627a3f251). The round's ablation and my read of the tree are describing one object.
L6 — the absence claim, with its control in the same run. .claude/hooks/guard-main-checkout.selftest.sh must appear exactly once on the merge commit and be unchanged — ⛔ "exactly once", never "zero": the tombstone surviving is the assertion, and a leg that only checked it was not modified would pass equally if it had been deleted.
⛔ NOT MEASURED, deliberately: the gate's own verdict. check-upstream-port-parity.mjs imports node builtins only, so this seat can run it — and that is the trap rather than the opportunity. Run from this checkout it returns exit 0 with four green lines about a pre-objectui#8288 ledger shape from 2026-09-06, in the right format, with no indication which tree it read. ⇒ CI's run on this head is the reading. The full account is §3 of the ACCEPT above; it is the most useful thing this round taught me.
A leg that comes back amber will be published with its cause. ⛔ It will not be re-run into green.
Generated by Claude Code
LANDED —
|
| leg | reading |
|---|---|
| L1 file set | 1 — scripts/upstream-port-pin.json ✅ |
| L2 triage's stop condition | git diff --numstat = 140 0 ✅ — ⛔ the zero is the assertion, and it held |
| L3 what must STAY | upstream block identical; removed = []; the three pre-existing entries byte-identical object-for-object ✅ |
| L4 what moved | entries 3 → 4, distinct refs 2 → 3; ref 61362932b5ad4c85b39169e70cf9be64d4332ce5, upstreamSha256 0da45049c680c2b2d58d52d637f17f7c45421a46a92a8dd0e6385dadb384dffa, 22 divergences, every why ≥ 10 chars ✅ |
| L5 nothing moved in transit | blob 2ea9063b406f3be7518f4c81362bc77a379db251 ✅ — the same object the round's two ablations used as their baseline |
| L6 the tombstone survives | the governed .claude/hooks/guard-main-checkout.selftest.sh entry appears exactly once and is unchanged ✅ — ⛔ "exactly once", never "zero" |
⭐ L3 and L6 are the ones worth naming. This ledger already holds a governed-surface entry, and the failure this PR could have had is not a wrong digest — it is a re-sync that quietly swept that entry up. The deep-compare says it did not.
⛔ What this green does NOT say
It says what landed. It does not re-run check-upstream-port-parity.mjs — this seat can execute it (node builtins only), and that is exactly why it is excluded: run from this checkout it returns exit 0 with four confident green lines about a pre-objectui#8288 ledger shape from 2026-09-06, in the right format, naming no tree. CI's run on this head is the reading.
⭐ What the round established that the card did not
- The convenience trap was undetectable, not merely forbidden. Upstream has not touched this file since
6136293, so upstreammaintoday carries the same blob — the wrong ref would have produced a fully green gate with a false provenance line, objectui#8288's exact failure re-created inside the card written to prevent it. - The ledger's ref convention is tip-at-read-time, read off entry 3 — which is pinned at a commit that does not touch its own file. No card mentions it, and getting it wrong would also have been green.
- The port's own header names
POPULATION_ROOTSdeclaringe2e/**where upstream declares.githooks/**as "THE PORT'S ONE SUBSTANTIVE CHANGE" — it is 1 of 22 divergences and no card mentions it either.
Closing objectui#8694. objectui#9206 stays open: this PR makes its own subject's prose false, and ⛔ fixing it here would have changed the very divergence pairs the PR declares.
Generated by Claude Code
Fixes #8694
scripts/check-bash32-floor.mjswas ported from objectstack and left out ofscripts/upstream-port-pin.json, so it had no drift gate — the exact failure class it exists to catch, since a construct missing fromCONSTRUCTSreads as an approval. objectui#8288 retired the ledger-wideupstream.ref, so it can now be registered at the revision it was actually taken from without disturbing any other entry.One new
files[]entry. 140 insertions, 0 deletions, one file.The ref:
61362932b5ad4c85b39169e70cf9be64d4332ce5Deriving it was the work of the card, so here is how, and what is wrong with each alternative.
Three independent statements name
6136293, and none of them was taken on trust:PORTED from objectstack-ai/objectstack scripts/check-bash32-floor.mjs at commit 6136293;.github/workflows/lint.yml:306—Ported from objectstack scripts/check-bash32-floor.mjs at 6136293;taken from objectstack 6136293.⭐ The proof is not any of those three; it is byte equality. Reversing the 22 declared divergences out of this repository's copy reconstructs upstream's blob at
61362932bexactly —reconstruction === upstreamistrueas raw text, not merely as a digest — and the forward direction round-trips too. A ref that was not the source could not do that.Rejected alternatives, each with what would have been wrong:
maintoday (ce7bae8b4)git rev-parseon both trees returnsf453895ba…), so the digest would have verified and nothing would have gone red — which is precisely what makes it dangerous. The ref documents which tree a human actually read; nobody readce7bae8b4. Any upstream change between the two would have been absorbed into the divergence list as an "adaptation", inverting the gate.abc10b27b, the last commit that TOUCHED the file at or before the port.claude/hooks/guard-main-checkout.selftest.shentry is pinned at70e77ec3b— adocs(rest)commit — while that file's last-touching commit isc2520416c. So the convention is tip-at-read-time, which is also what--resync --reftakes from the operator.bf10debd5or70e77ec3b, the refs already in the ledgerThe acceptance probe, both verdict lines verbatim
Captured by redirect-then-capture, never through a pipe.
Before —
exit=0:After —
exit=0:The 22 divergences
Derived from the real
diff, not assumed: a minimal changed-region set with one line of context, expanded until each snippet is unique. The card named one (the shebang census); it ispopulation-shebang-census-is-zero-here, and it is 1 of 22.--listreports every one of them as1 match(es) in the ported copy, so no anchor is ambiguous.The substantive ones, as opposed to the header-and-prose ones:
population-roots-literal(this repository declarese2e/**where upstream declares.githooks/**— two of the four shell files it wrote itself live there),real-tree-legs-replace-byshebang-floor(upstream'slive.byShebang > 0is red here on day one),clean-tree-census-asserted-by-count, and the objectui#8404 host-premise family.Proof the new entry can FAIL, two-sided
Both legs mutate on disk, prove the mutation landed before reading anything, and restore under
trap … EXIT INT TERM.2ea9063b4…moved to985a320c3…exit=1,reconstruction does not match the pinned upstream blob, and it prints both digestspopulation-roots-literal.portedcorrupted)2ea9063b4…moved to627a3f251…exit=1,divergence `population-roots-literal`: expected its ported text exactly once, found 0Restore proven both ways after each leg and at the end:
git hash-objectequals theHEADblob2ea9063b406f3be7518f4c81362bc77a379db251, andgit diff HEADis empty. The restore namesHEADexplicitly rather than using a baregit checkout --, which would have taken the mutation back out of the index.Gates, by required context
node scripts/check-upstream-port-parity.mjs --self-testexit=0—✓ check-upstream-port-parity self-test: 58 cases passTest (shard N/4)pnpm exec vitest run scripts/exit=0—Test Files 148 passed | 2 skipped (150),Tests 4395 passed | 2 skipped (4397)Type Checkpnpm exec tsc -p tsconfig.scripts.jsonexit=0, no outputChangeset Declarationnode scripts/check-changeset-presence.mjsexit=0—✅ No source or published contract of a released package changed in this range, so no changeset is owed.The gate's own line is the authority here: a ledger JSON is not published package source. No changeset and no label.Control Byte Scannode scripts/check-control-bytes.mjsexit=0—✅ check-control-bytes: OK (scanned 7400 tracked text file(s); skipped 85 binary).LintDeclared narrowing for
Lint, with its three measurements. eslint's own population, read from--format jsonon a repo-wide run rather than guessed: 4,849 files, of which 0 are.json. The changed file is not among them; the control,scripts/check-upstream-port-parity.mjs, is. eslint says so itself a second way:--print-config scripts/upstream-port-pin.jsonprintsundefinedwhile the same command on the.mjsreturns a config object. Invariance:eslint.config.jsconfigures no type-aware linting (noproject,projectServiceorparserOptions.project), so a file outside the population cannot move any other file's verdict — and the diff changes exactly one file.Declared narrowing for
Test. Two files in the whole repository read the pin path at runtime, both underscripts/:scripts/__tests__/upstream-port-parity-wiring.test.tsand the gate itself. Grep printed its matched lines and ran with a control that hit. The fullscripts/test population ran, not just the one file.The stop condition: exactly one entry
git diff --numstatreads140 0— zero lines removed, so no existing line was touched at all, let alone an existing entry. Independently, the three pre-existing entries deep-compare identical before and after the write. The.claude/hooks/guard-main-checkout.selftest.shentry is byte-identical and no re-sync was run against it. Governed-surface verdict for the changed path:NOT GOVERNED — 1 path(s) checked against 5 governed surface(s); none matched, withAGENTS.mdas the control returningGOVERNEDin the same run.Out of scope, filed not folded: objectui#9206
Registering the file makes its own prose false, and the fences forbid editing it here — correctly, since editing the ported bytes would change the very divergence pairs this PR declares. Two locations, one argument written twice:
scripts/check-bash32-floor.mjslines 11, 162 and 170 still say it is not registered;.github/workflows/lint.ymllines 306-313 still describe the retired globalupstream.refas the blocker. That copy is false onorigin/maintoday, independent of this PR: objectui#8385 item 1 corrected only the.mjs— its changeset names that file alone — and this second copy was missed.Two of the new entry's divergence
whyfields record the obligation in the ledger, so the next reader of the pin stands on it.🤖 Generated with Claude Code
https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
Generated by Claude Code