Uh oh!
There was an error while loading. Please reload this page.
fix(scripts): make the R7a bash-3.2 control hold on a host that IS bash 3.2 - #12298
Merged
Merged
Conversation
…sh 3.2 R7a probed `mapfile` itself to prove the BASH_ENV harness really removes a builtin. On stock macOS `/bin/bash` is 3.2, so `mapfile` is absent from the PLAIN run too — `plain=` came back empty exactly like `sim.out=`, the assertion could not be satisfied by any correct harness, and `check:objectui-changeset` sat red on every macOS seat while CI (ubuntu-latest, bash 5) stayed green. Option B: the probe builtin is now chosen at RUNTIME from bash 2.x-era builtins the host itself reports as builtins and that have no external `/usr/bin` twin, so `enable -n` on one yields the same 127 "command not found" a missing bash-4 builtin yields on 3.2. No skip leg: a host offering no qualifying builtin reddens loudly. A second leg, R7a2, asserts the state R7b actually depends on — mapfile unavailable in the R7b shell — which holds on both hosts for different reasons, so neither host can pass R7b vacuously. `scripts/bump-objectui.sh` is untouched; R7/R7b/R7c still redden when a bash-4 builtin is reintroduced into it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjM2ia8Av1v5NqfqQEQmC6
This was referenced Aug 25, 2026
yinlianghui
marked this pull request as ready for review
August 25, 2026 17:11
This was referenced Aug 25, 2026
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#12254
What was red
pnpm check:objectui-changesetexits 1 on every stock macOS seat — not on the rule itgates, but on the R7a control leg#12071 added. R7a proved the BASH_ENV harness was
real by running a
mapfileprobe plain and simulated and requiring that only thesimulated one fail. On stock macOS
/bin/bashis 3.2, somapfileis missing from theplain run too:
plain=came back empty exactly likesim.out=, and "the simulationremoved something" could not be satisfied by any correct harness.
I read the code before trusting the card, and the card's account is exactly right —
scripts/objectui-changeset-digest.mjsreally did probemapfileitself, both ways, andassert
probePlain.stdout.includes('MAPFILE-WORKS').A control written to stop a vacuous pass had become a guaranteed fail on one platform
— the same error family one level up: a check whose own precondition was never measured
across the population of hosts it runs on.
The option search — B, and the builtin is chosen by the host
The card leaves the choice open and conditions the preference: "B is the better shape if
a suitable builtin exists." So I searched rather than assumed. Across every bash builtin
with no external
/usr/bintwin,enable -n NAMEproduces exactly the status-127command not foundthat a missing bash-4 builtin produces on 3.2 — measured here:So option B is available. But naming one builtin and asserting it exists on bash 3.2
would repeat the precise mistake this card is about — a hardcoded belief about another
platform's builtin table, held by someone who cannot run that platform. So the fix does
not hardcode one. It asks the host:
probeBuiltinis selected at runtime from thecandidates above, keeping the first the shell itself reports as a builtin (
type -t==builtin) with no external twin (type -Pempty). On this container it picksshopt.The leg is then unconditional and measures the harness, not the platform.
⛔ Not a skip. A host offering no qualifying builtin reddens loudly. Option A's
SKIPPED:leg was not needed and is not present — swapping one vacuity for another wasnever on the table.
A second leg for the state R7b actually depends on
R7a2asserts that in the shell R7b runs,mapfileis unavailable. That holds on bothhosts for different reasons —
enable -nremoved it on bash 5, it was never there onbash 3.2 — so it is its own leg rather than folded into R7a. Neither leg alone is
unconditional; together they leave no host on which R7b can pass vacuously. The detail line
names which way the host got there, so a macOS operator reading a green run still learns
their
/bin/bashis the genuine 3.2 article.This container is Linux with bash 5.2.21. Nobody on this lane can stand on the platform
where the bug reproduces, and this PR does not claim to. No run below happened on macOS.
What was done instead: the failing condition was constructed locally — a
BASH_ENVfile that disables
mapfile/readarraymakes everybashthis self-test spawns genuinelylack the builtin, which is the mechanism the macOS failure runs on. On
origin/mainthatreproduces the reported symptom byte-for-byte:
Same tree, after this change:
EXIT=0.Still unverified from this seat, stated plainly rather than papered over:
absent), not the platform. A 3.2-specific difference in
type -t/type -P/enable -nwould not be visible here. The runtime probe selection is what makes that gapsurvivable: the host answers for itself, and if
shoptwere somehow not a builtin there,the next candidate is taken and a host with none reddens rather than lying.
shopt/caller/compgenship in bash 3.2. Outbound fetchesof the bash sources are blocked from this container (
git.savannah.gnu.org→ proxy 403;bminor/bash→ not in this session's allowed repo set). This PR therefore does notrest on that claim — which is the point of selecting at runtime.
Acceptance
(a) The gate goes green where it was red — demonstrated on the constructed
builtin-less shell, not claimed for macOS:
origin/main(b) R7b still fails if
bump-objectui.shreintroduces a bash-4 builtin.scripts/bump-objectui.shis untouched by this PR. Mutation: amapfileline injectedafter
set -euo pipefail, confirmed on disk by grepping for the injected marker (aneditor's exit code is not evidence —
perl -ireturns 0 on zero matches):Restored and proven byte-identical:
git hash-object=git rev-parse HEAD:=c1ff2049c4e18585dc85d40ad4e7369a1c7ce3b9,git status --porcelainempty.builtin-less host the same mutation aborts the self-test earlier than R7b — an uncaught
execFileSyncthrow at digest line 1516, since every leg there already runs on amapfile-less shell. Still a loud red naming
mapfile: command not found, but not R7b'sassertion. Verified pre-existing by replaying the mutation against
origin/main's owndigest: identical abort, same line. Not introduced here.
The new control is itself non-vacuous — proven by mutation
Two mutations, each confirmed on disk before it was read, each restored under an
EXITtrap:
on both host shapes —
builtin=shopt plain=PROBE-STATUS=0 sim=PROBE-STATUS=0. Thisis the property the old leg could not have: it was red on the 3.2-shaped host whether
the harness worked or not.
host-has-mapfile=true … sim.out=MAPFILE-WORKS— while R7b passes. That is thevacuous pass R7a exists to prevent, caught.
Two things found while verifying, reported not fixed
check:objectui-changesetis a stepin
.github/workflows/lint.yml, which declares nopaths:filter — it runs on everyPR to
main. Anddispatch-gates.mjsreaches it throughpendingChangesetFamilies, thechangeset-directory probe, so every card that writes a changeset derives it. Not "a
broad set of paths": effectively every card in the repo.
ubuntu-latestwithbash 5; the failure exists only where
/bin/bashis 3.2. Nothing in the pipeline willever catch the next one, which is why this sat red locally on every macOS seat with every
PR reporting green. Not fixed here — out of scope for this card, and A repo-wide
check:for bash-4-only constructs in tracked *.sh — measured 4-for-4, but it needs a new gate file plus wiring #12221 (a repo-widebash-4 gate) is the adjacent lane. Recorded so the gap is on the record.
Related and deliberately not folded in: #12221 and #12222 are separate cards.
Verification
Gate union derived at the final commit with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(noSTALE TREEwarning; change set = 1 path, three-dot semantics). All 9 matched families run at
10ddefd88a, exit codes captured before any pipe, each gate's own verdict line quoted:check-ci-filter-parityfirst exited 1 withPREREQUISITE NOT MET — the dependency 'yaml' is not installed; its own text says "Nothing was measured … It is NOT a finding."pnpm install, then green. Working tree clean at that commit.Declared narrowing: the 9 families above were run directly rather than through
scripts/pm/os-verify-lock.sh. They are static node gates — no build, no test suite — andthe lock was held by another agent's build (391s held, one waiter) at the time. No
repo-wide
pnpm lintsweep was run; CI runs the farm exactly once regardless.Changeset: none. This is a gate self-test with no user-visible surface —
skip-changeset.Generated by Claude Code