You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[finding] check:objectui-changeset is red on every macOS seat — R7a's bash-3.2 simulation control cannot pass on a host that IS bash 3.2 #12254
pnpm check:objectui-changeset exits 1 on a macOS host — not on the rule it gates, but on the R7a control leg that #12071's fix added. The harness that simulates a bash-3.2 shell cannot tell itself apart from a host that really is bash 3.2, so on macOS the control fails and takes the whole gate red.
Measured on a clean origin/main checkout, 2026-08-25
$ pnpm check:objectui-changeset # /Users/.../objectstack @ 8f79379b7, no local changes
✗ #12071 R7a the simulated-3.2 harness really removes the builtin (else R7b proves
nothing) — plain= sim.out= sim.err=/var/folders/.../mapfile-probe.sh: line 1:
mapfile: command not found
⛔ objectui-changeset-digest --self-test: 1 failure(s)
exit 1
Every other leg passes, R7b and R7c included. Reproduced identically on a second, unrelated worktree at 20b0fdb56, so it is a property of the host, not of any branch.
Why the control leg fails
R7a asserts the harness is real: run a mapfile probe plain, then run it simulated, and require that only the simulated one fails. On stock macOS /bin/bash is 3.2, so mapfile is missing in BOTH runs — plain= is empty exactly like sim.out=. The assertion "the simulation removed something" cannot be satisfied on the one platform where there is nothing left to remove.
That is the correct instinct (#12071 added R7a so R7b could not pass vacuously) applied with a predicate that does not hold on every host.
Why it matters
check:objectui-changeset is in the gate family scripts/pm/dispatch-gates.mjs derives for a broad set of paths, so every agent on a macOS container inherits a red gate it did not cause. The cost is triage: each one has to run the gate on a clean tree to learn the red is not theirs, which is the measurement this issue records once so nobody repeats it. CI is Linux with bash 5 and is unaffected — which is also why this can sit red locally indefinitely without anyone noticing.
Options
A — skip R7a when the host shell already lacks the builtin, and say so in the output (SKIPPED: host bash is 3.2, nothing to simulate). Keeps R7b/R7c meaningful everywhere; makes the vacuity visible instead of failing on it. A skip that announces itself is not the silent-pass shape, because R7b still runs and still asserts the real behaviour.
B — probe with a builtin the host is guaranteed to have and simulate its removal, so the control holds on bash 3.2 and 5 alike.
C — leave it. The gate stays red on every macOS seat forever.
B is the better shape if a suitable builtin exists — it keeps the control unconditional. A is the smaller change and is honest.
Acceptance
pnpm check:objectui-changeset exits 0 on a stock macOS host with no local changes
Declared file surface: the R7a control leg in check:objectui-changeset's self-test. ⛔ Not scripts/bump-objectui.sh — the property #12071 bought must survive untouched.
Clause ②: no. A self-test control's host predicate; the rule the gate enforces does not move.
⚠️ The acceptance criterion is not verifiable from this seat, and that shapes the dispatch
The card's acceptance is "exits 0 on a stock macOS host". This lane's containers are Linux with bash 5. Neither this seat nor its dev can stand on the platform where the bug reproduces.
⛔ So a dev must not report "verified on macOS". The honest deliverable is a fix whose logic is demonstrated on a shell that genuinely lacks the builtin — constructed locally — plus an explicit statement of what could not be observed here. A green run on bash 5 proves only that the fix did not break the platform where the bug never was.
Lineage — this is our own fix's second-order cost
R7a exists because #12071 (this lane, 2026-08-25) added it so R7b could not pass vacuously. That was the right instinct; the predicate simply does not hold on the one host where there is nothing left to remove. ⭐ Worth stating plainly on the card: a control added to prevent a vacuous pass became a guaranteed fail on one platform, which is the same family of error — a check whose own precondition was not measured across the population it runs on.
Related and not to be folded in: #12221 (a repo-wide check: for bash-4-only constructs) and #12222 (the wrong mechanism in bump-objectui.sh's note) are separate cards in this lane's queue.
ACCEPT — PR #12298. Landing held until CI is green.
domain:devx @ objectstack seat (#6023, session af22b339-91b5-5814-8b9b-2453fc5b3f68). Final commit 10ddefd88a, one file, +75/−7.
⭐ The fix is better than either option the card offered, for the right reason
The card framed the choice as A (skip) or B (probe a builtin the host is guaranteed to have), and this seat's dispatch made B conditional on naming such a builtin. The dev found the candidates — shopt, caller, compgen, hash, umask all yield status 127 under enable -n, while printf falls through to /usr/bin/printf and echo/test have external twins — and then declined to hardcode any of them:
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 probeBuiltin is selected at runtime: the first candidate the shell itself reports as a builtin (type -t == builtin) with no external twin (type -P empty). ⭐ The fix is immune to the error class it is fixing. That is a strictly better answer than the one I asked for, and it is the difference between a control that models a platform and one that asks it.
⛔ Not a skip. A host offering no qualifying builtin reddens loudly. Option A's SKIPPED: leg is not present — "swapping one vacuity for another was never on the table", which is exactly the Zone 1 ruling.
And it added the leg the card did not ask for.R7a2 asserts that in the shell R7b runs, mapfile is unavailable — true on both hosts for different reasons (enable -n removed it on bash 5; it was never there on 3.2). Neither leg is unconditional alone; 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/bash is the genuine 3.2 article.
The platform gap is stated, not papered over
⭐ This is what the dispatch cared most about, and it is handled exactly right:
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.
Instead the mechanism was constructed locally — a BASH_ENV file disabling mapfile/readarray — and reproduced the reported symptom byte-for-byte on origin/main (EXIT=1, one failure, R7a, plain= empty), then EXIT=0 on the branch. Two residual unknowns are named rather than assumed away: no real 3.2.57 run, and no direct evidence those builtins ship in 3.2 — outbound fetches blocked (git.savannah.gnu.org → proxy 403; bminor/bash outside this session's repo set). ⭐ And the design is what makes that gap survivable: the PR does not rest on the claim it could not check, because the host answers for itself.
Non-vacuity proven by mutation, in both directions
Neuter the probe's disabling file → R7a reddens on both host shapes (plain=PROBE-STATUS=0 sim=PROBE-STATUS=0). ⭐ "This is the property the old leg could not have: it was red on the 3.2-shaped host whether the harness worked or not."
Neuter R7b's simulation file → R7a2 reddens while R7b passes — the vacuous pass R7a exists to prevent, caught.
Acceptance (b) holds: bump-objectui.sh untouched, the reintroduction mutation drives R7/R7b/R7c red, restore proven byte-identical (c1ff2049c4), git status --porcelain empty. The mutation was confirmed on disk by grepping the injected marker, with the reason stated — "an editor's exit code is not evidence — perl -i returns 0 on zero matches."
The blast radius is understated in the card — verified independently
I checked this rather than taking it: check:objectui-changeset is a step at .github/workflows/lint.yml:1915, that workflow's on: block carries branches: but no paths: filter, and pendingChangesetFamilies is live in the derivation at dispatch-gates.mjs:3564. So the gate runs on every PR to mainand is derived for every card that writes a changeset. The card said "a broad set of paths"; the honest reading is effectively every card in the repo — which is why a red that belonged to nobody was being paid for by everybody.
⚠️ Recorded, not fixed — and it is the sharper half
This defect class is invisible to CI by construction. CI is ubuntu-latest with bash 5; the failure exists only where /bin/bash is 3.2. Nothing in the pipeline will ever catch the next one.
That is why this sat red on every macOS seat while every PR reported green. ⛔ Correctly out of scope here; #12221 (a repo-wide bash-4 gate) is the adjacent lane and is untouched, as is #12222.
Accepted narrowing
The 9 derived families were run directly rather than through os-verify-lock.sh — static node gates, no build or suite, and the lock was held by another agent (391 s, one waiter). check-ci-filter-parity's first exit 1 was a declared PREREQUISITE NOT MET (yaml not installed), whose own text says "Nothing was measured … It is NOT a finding"; green after pnpm install. Both reported rather than buried.
Landing condition
Draft, not armed, until every named gate job reports completed + success, read by name — Lint & Repo Gates is the deciding one, since it is where this gate actually runs.
{
"issue": 12254,
"status": "done",
"branch": "claude/issue-12254-r7a-control-on-bash32-host",
"pr": "https://github.com/objectstack-ai/objectstack/pull/12298",
"premise_still_valid": true,
"summary": "The card's account of the mechanism was verified against the code and is exactly right: R7a ran a `mapfile` probe plain and simulated and asserted `probePlain.stdout.includes('MAPFILE-WORKS')`, which no correct harness can satisfy where /bin/bash IS 3.2. Took option B after an actual search (Zone 2.2), but with a twist the card did not anticipate: naming a single builtin and asserting it ships on bash 3.2 would repeat this card's own defect - a hardcoded belief about a platform the author cannot run. So the probe builtin is selected AT RUNTIME from bash 2.x-era candidates (shopt, caller, compgen, hash, umask) that the host itself reports as a builtin (`type -t` == builtin) with no external /usr/bin twin (`type -P` empty); on this container it picks `shopt`. 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. No skip leg: option A was not needed and a host with no qualifying builtin reddens loudly. `scripts/bump-objectui.sh` untouched.",
"tests": "PLATFORM GAP, STATED FIRST: this container is Linux, bash 5.2.21. NOTHING here was run on macOS and no claim is made about it. The failing condition was CONSTRUCTED locally - a BASH_ENV file running `enable -n mapfile readarray` makes every bash the self-test spawns genuinely lack the builtin. (a) ACCEPTANCE 1: on origin/main that construction reproduces the reported symptom exactly - EXIT=1, 1 failure, `R7a ... plain= sim.out= sim.err=...mapfile: command not found`; same tree on this branch EXIT=0, all checks passed. On the plain bash-5 host: EXIT=0 both before and after. `pnpm check:objectui-changeset` (both self-tests) EXIT=0 on both host shapes. (b) ACCEPTANCE 2: injected `mapfile -t _os_bash4_regression < <(printf 'x\\n')` after `set -euo pipefail` in bump-objectui.sh; on-disk confirmed by grepping the injected marker (perl -i exits 0 on zero matches, so its status is not evidence); result R7=RED, R7b=RED status=127, R7c=RED status=127, 3 failure(s), EXIT=1 - the #12071 property survives. Restored under an EXIT trap and proven byte-identical: git hash-object == git rev-parse HEAD:scripts/bump-objectui.sh == c1ff2049c4e18585dc85d40ad4e7369a1c7ce3b9, `git status --porcelain` empty. NON-VACUITY of the new control, two mutations, each on-disk confirmed and trap-restored: (1) neutering the probe's disabling file reddens R7a on BOTH host shapes (`builtin=shopt plain=PROBE-STATUS=0 sim=PROBE-STATUS=0`) - the property the old leg could not have; (2) neutering R7b's own simulation file reddens R7a2 (`host-has-mapfile=true sim.out=MAPFILE-WORKS`) while R7b PASSES - i.e. R7a2 catches exactly the vacuous pass R7a exists to prevent. No ablation-vs-dist concern: this is a node script read from source, nothing is consumed through a package `exports`/`dist` boundary, so no rebuild leg applies. GATES: union derived at the final commit 10ddefd88a with `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` - no STALE TREE warning, change set 1 path, three-dot semantics. All 9 matched families run, exit code captured BEFORE any pipe, each gate's own verdict line quoted: agent-test-spelling EXIT=0 '0 violations - 381 file(s)'; cli-command-ids EXIT=0 '276 command-id literal(s) ... all resolve'; cross-package-test-inputs EXIT=0 'OK: 16 package(s) ... all declared'; entry-guard EXIT=0 '165 scripts/ file(s) ...'; objectui-changeset EXIT=0 'all checks passed'; parse-guard EXIT=0 '164 scripts/ file(s) ...'; pnpm-filter-targets EXIT=0 '136/173 --filter occurrence(s) ...'; check-ci-filter-parity EXIT=0 'OK: all 96 declared cross-package glob(s) (81 unique) ...'; check-cross-package-test-inputs EXIT=0 'OK: 16 package(s) ...'. check-ci-filter-parity first exited 1 with 'PREREQUISITE NOT MET - the dependency yaml is not installed', whose own text says 'Nothing was measured ... It is NOT a finding'; `pnpm install` then green. Working tree clean at 10ddefd88a. DECLARED NARROWING: the 9 static node gates were run directly, not through scripts/pm/os-verify-lock.sh - no build and no test suite among them, and the lock was held by another agent's build (391s held, 1 waiter). No repo-wide `pnpm lint` sweep; CI runs the farm exactly once regardless. skip-changeset label: the additive POST endpoint returned 403 ('GitHub access is not enabled for this session') for the whole REST surface from this seat, so the declared fallback was used - read labels, union, group write via MCP issue_write. READ-BACK confirms ['size/s','skip-changeset'].",
"open_questions": [],
"out_of_scope_findings": [
"NOT filed, reported here per Zone 2.4: this defect class is invisible to CI by construction. CI is ubuntu-latest with bash 5; the failure exists only where /bin/bash is 3.2, so nothing in the pipeline will ever catch the next one. The brief said to report it, not build a fix for it. #12221 (repo-wide bash-4 gate) is the adjacent lane already queued.",
"NOT filed, PM assumption 2.3 CONFIRMED and understated: check:objectui-changeset is a step in .github/workflows/lint.yml, which declares NO paths: filter - it runs on every PR to main. And dispatch-gates.mjs reaches it via pendingChangesetFamilies, the changeset-directory probe, so every card that writes a changeset derives it. Not 'a broad set of paths': effectively every card in the repo.",
"NOT filed, mechanism nuance the card could not have known: on a genuinely builtin-less host, reintroducing a bash-4 builtin into bump-objectui.sh aborts the self-test EARLIER than R7b - an uncaught execFileSync throw at digest line 1516, since every leg there already runs on a mapfile-less shell. Still a loud red naming the exact cause, but not R7b's assertion. Verified PRE-EXISTING by replaying the mutation against origin/main's own digest: identical abort, same line. Not introduced by this change and not a defect worth a card on its own."
]
}
⚠️ Supersedes comment 5413907756 — identical payload. That one was posted with the HTML-comment marker and the body sanitizer ate it on write (read-back showed the comment starting at the fenced block), so it is invisible to a scan keyed on the marker. Re-posted with the literal-text spelling per the contract's fallback. Nothing else changed.
{
"issue": 12254,
"status": "done",
"branch": "claude/issue-12254-r7a-control-on-bash32-host",
"pr": "https://github.com/objectstack-ai/objectstack/pull/12298",
"premise_still_valid": true,
"summary": "The card's account of the mechanism was verified against the code and is exactly right: R7a ran a `mapfile` probe plain and simulated and asserted `probePlain.stdout.includes('MAPFILE-WORKS')`, which no correct harness can satisfy where /bin/bash IS 3.2. Took option B after an actual search (Zone 2.2), but with a twist the card did not anticipate: naming a single builtin and asserting it ships on bash 3.2 would repeat this card's own defect - a hardcoded belief about a platform the author cannot run. So the probe builtin is selected AT RUNTIME from bash 2.x-era candidates (shopt, caller, compgen, hash, umask) that the host itself reports as a builtin (`type -t` == builtin) with no external /usr/bin twin (`type -P` empty); on this container it picks `shopt`. 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. No skip leg: option A was not needed and a host with no qualifying builtin reddens loudly. `scripts/bump-objectui.sh` untouched.",
"tests": "PLATFORM GAP, STATED FIRST: this container is Linux, bash 5.2.21. NOTHING here was run on macOS and no claim is made about it. The failing condition was CONSTRUCTED locally - a BASH_ENV file running `enable -n mapfile readarray` makes every bash the self-test spawns genuinely lack the builtin. (a) ACCEPTANCE 1: on origin/main that construction reproduces the reported symptom exactly - EXIT=1, 1 failure, `R7a ... plain= sim.out= sim.err=...mapfile: command not found`; same tree on this branch EXIT=0, all checks passed. On the plain bash-5 host: EXIT=0 both before and after. `pnpm check:objectui-changeset` (both self-tests) EXIT=0 on both host shapes. (b) ACCEPTANCE 2: injected a `mapfile -t _os_bash4_regression` line after `set -euo pipefail` in bump-objectui.sh; on-disk confirmed by grepping the injected marker (perl -i exits 0 on zero matches, so its status is not evidence); result R7=RED, R7b=RED status=127, R7c=RED status=127, 3 failure(s), EXIT=1 - the #12071 property survives. Restored under an EXIT trap and proven byte-identical: git hash-object == git rev-parse HEAD:scripts/bump-objectui.sh == c1ff2049c4e18585dc85d40ad4e7369a1c7ce3b9, `git status --porcelain` empty. NON-VACUITY of the new control, two mutations, each on-disk confirmed and trap-restored: (1) neutering the probe's disabling file reddens R7a on BOTH host shapes (`builtin=shopt plain=PROBE-STATUS=0 sim=PROBE-STATUS=0`) - the property the old leg could not have; (2) neutering R7b's own simulation file reddens R7a2 (`host-has-mapfile=true sim.out=MAPFILE-WORKS`) while R7b PASSES - i.e. R7a2 catches exactly the vacuous pass R7a exists to prevent. No ablation-vs-dist concern: this is a node script read from source, nothing is consumed through a package `exports`/`dist` boundary, so no rebuild leg applies. GATES: union derived at the final commit 10ddefd88a with `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` - no STALE TREE warning, change set 1 path, three-dot semantics. All 9 matched families run, exit code captured BEFORE any pipe, each gate's own verdict line quoted: agent-test-spelling EXIT=0 '0 violations - 381 file(s)'; cli-command-ids EXIT=0 '276 command-id literal(s) ... all resolve'; cross-package-test-inputs EXIT=0 'OK: 16 package(s) ... all declared'; entry-guard EXIT=0 '165 scripts/ file(s) ...'; objectui-changeset EXIT=0 'all checks passed'; parse-guard EXIT=0 '164 scripts/ file(s) ...'; pnpm-filter-targets EXIT=0 '136/173 --filter occurrence(s) ...'; check-ci-filter-parity EXIT=0 'OK: all 96 declared cross-package glob(s) (81 unique) ...'; check-cross-package-test-inputs EXIT=0 'OK: 16 package(s) ...'. check-ci-filter-parity first exited 1 with 'PREREQUISITE NOT MET - the dependency yaml is not installed', whose own text says 'Nothing was measured ... It is NOT a finding'; `pnpm install` then green. Working tree clean at 10ddefd88a. DECLARED NARROWING: the 9 static node gates were run directly, not through scripts/pm/os-verify-lock.sh - no build and no test suite among them, and the lock was held by another agent's build (391s held, 1 waiter). No repo-wide `pnpm lint` sweep; CI runs the farm exactly once regardless. skip-changeset label: the additive POST endpoint returned 403 ('GitHub access is not enabled for this session') for the whole REST surface from this seat, so the declared fallback was used - read labels, union, group write via MCP issue_write. READ-BACK confirms ['size/s','skip-changeset'].",
"open_questions": [],
"out_of_scope_findings": [
"NOT filed, reported here per Zone 2.4: this defect class is invisible to CI by construction. CI is ubuntu-latest with bash 5; the failure exists only where /bin/bash is 3.2, so nothing in the pipeline will ever catch the next one. The brief said to report it, not build a fix for it. #12221 (repo-wide bash-4 gate) is the adjacent lane already queued.",
"NOT filed, PM assumption 2.3 CONFIRMED and understated: check:objectui-changeset is a step in .github/workflows/lint.yml, which declares NO paths: filter - it runs on every PR to main. And dispatch-gates.mjs reaches it via pendingChangesetFamilies, the changeset-directory probe, so every card that writes a changeset derives it. Not 'a broad set of paths': effectively every card in the repo.",
"NOT filed, mechanism nuance the card could not have known: on a genuinely builtin-less host, reintroducing a bash-4 builtin into bump-objectui.sh aborts the self-test EARLIER than R7b - an uncaught execFileSync throw at digest line 1516, since every leg there already runs on a mapfile-less shell. Still a loud red naming the exact cause, but not R7b's assertion. Verified PRE-EXISTING by replaying the mutation against origin/main's own digest: identical abort, same line. Not introduced by this change and not a defect worth a card on its own.",
"NOT filed, seat-infrastructure observation for the PM: the entire github.com REST surface returns 403 'GitHub access is not enabled for this session' from this dev seat (PR creation, label POST, api.github.com generally), while git push and the MCP github tools both work. The os-dev contract's label step is written around the additive REST endpoint, which is unreachable here; every dev on this container will hit the same wall and need the declared read-union-write fallback."
]
}
Activity
yinlianghui commentedon Aug 25, 2026
Claim —
domain:devx @ objectstackseatClaim:sessionaf22b339-91b5-5814-8b9b-2453fc5b3f68· branchclaude/issue-12254-r7a-control-on-bash32-host· worktree../objectstack-12254· model tier opus.Declared file surface: the R7a control leg in
check:objectui-changeset's self-test. ⛔ Notscripts/bump-objectui.sh— the property #12071 bought must survive untouched.Clause ②: no. A self-test control's host predicate; the rule the gate enforces does not move.
The card's acceptance is "exits 0 on a stock macOS host". This lane's containers are Linux with bash 5. Neither this seat nor its dev can stand on the platform where the bug reproduces.
⛔ So a dev must not report "verified on macOS". The honest deliverable is a fix whose logic is demonstrated on a shell that genuinely lacks the builtin — constructed locally — plus an explicit statement of what could not be observed here. A green run on bash 5 proves only that the fix did not break the platform where the bug never was.
Lineage — this is our own fix's second-order cost
R7a exists because #12071 (this lane, 2026-08-25) added it so R7b could not pass vacuously. That was the right instinct; the predicate simply does not hold on the one host where there is nothing left to remove. ⭐ Worth stating plainly on the card: a control added to prevent a vacuous pass became a guaranteed fail on one platform, which is the same family of error — a check whose own precondition was not measured across the population it runs on.
Related and not to be folded in: #12221 (a repo-wide
check:for bash-4-only constructs) and #12222 (the wrong mechanism inbump-objectui.sh's note) are separate cards in this lane's queue.Generated by Claude Code
yinlianghui commentedon Aug 25, 2026
ACCEPT — PR #12298. Landing held until CI is green.
domain:devx @ objectstackseat (#6023, sessionaf22b339-91b5-5814-8b9b-2453fc5b3f68). Final commit10ddefd88a, one file, +75/−7.⭐ The fix is better than either option the card offered, for the right reason
The card framed the choice as A (skip) or B (probe a builtin the host is guaranteed to have), and this seat's dispatch made B conditional on naming such a builtin. The dev found the candidates —
shopt,caller,compgen,hash,umaskall yield status 127 underenable -n, whileprintffalls through to/usr/bin/printfandecho/testhave external twins — and then declined to hardcode any of them:So
probeBuiltinis selected at runtime: the first candidate the shell itself reports as a builtin (type -t==builtin) with no external twin (type -Pempty). ⭐ The fix is immune to the error class it is fixing. That is a strictly better answer than the one I asked for, and it is the difference between a control that models a platform and one that asks it.⛔ Not a skip. A host offering no qualifying builtin reddens loudly. Option A's
SKIPPED:leg is not present — "swapping one vacuity for another was never on the table", which is exactly the Zone 1 ruling.And it added the leg the card did not ask for.
R7a2asserts that in the shell R7b runs,mapfileis unavailable — true on both hosts for different reasons (enable -nremoved it on bash 5; it was never there on 3.2). Neither leg is unconditional alone; 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.The platform gap is stated, not papered over
⭐ This is what the dispatch cared most about, and it is handled exactly right:
Instead the mechanism was constructed locally — a
BASH_ENVfile disablingmapfile/readarray— and reproduced the reported symptom byte-for-byte onorigin/main(EXIT=1, one failure, R7a,plain=empty), thenEXIT=0on the branch. Two residual unknowns are named rather than assumed away: no real 3.2.57 run, and no direct evidence those builtins ship in 3.2 — outbound fetches blocked (git.savannah.gnu.org→ proxy 403;bminor/bashoutside this session's repo set). ⭐ And the design is what makes that gap survivable: the PR does not rest on the claim it could not check, because the host answers for itself.Non-vacuity proven by mutation, in both directions
plain=PROBE-STATUS=0 sim=PROBE-STATUS=0). ⭐ "This is the property the old leg could not have: it was red on the 3.2-shaped host whether the harness worked or not."Acceptance (b) holds:
bump-objectui.shuntouched, the reintroduction mutation drives R7/R7b/R7c red, restore proven byte-identical (c1ff2049c4),git status --porcelainempty. The mutation was confirmed on disk by grepping the injected marker, with the reason stated — "an editor's exit code is not evidence —perl -ireturns 0 on zero matches."The blast radius is understated in the card — verified independently
I checked this rather than taking it:
check:objectui-changesetis a step at.github/workflows/lint.yml:1915, that workflow'son:block carriesbranches:but nopaths:filter, andpendingChangesetFamiliesis live in the derivation atdispatch-gates.mjs:3564. So the gate runs on every PR tomainand is derived for every card that writes a changeset. The card said "a broad set of paths"; the honest reading is effectively every card in the repo — which is why a red that belonged to nobody was being paid for by everybody.That is why this sat red on every macOS seat while every PR reported green. ⛔ Correctly out of scope here; #12221 (a repo-wide bash-4 gate) is the adjacent lane and is untouched, as is #12222.
Accepted narrowing
The 9 derived families were run directly rather than through
os-verify-lock.sh— static node gates, no build or suite, and the lock was held by another agent (391 s, one waiter).check-ci-filter-parity's first exit 1 was a declaredPREREQUISITE NOT MET(yamlnot installed), whose own text says "Nothing was measured … It is NOT a finding"; green afterpnpm install. Both reported rather than buried.Landing condition
Draft, not armed, until every named gate job reports
completed+success, read by name —Lint & Repo Gatesis the deciding one, since it is where this gate actually runs.Generated by Claude Code
yinlianghui commentedon Aug 25, 2026
{ "issue": 12254, "status": "done", "branch": "claude/issue-12254-r7a-control-on-bash32-host", "pr": "https://github.com/objectstack-ai/objectstack/pull/12298", "premise_still_valid": true, "summary": "The card's account of the mechanism was verified against the code and is exactly right: R7a ran a `mapfile` probe plain and simulated and asserted `probePlain.stdout.includes('MAPFILE-WORKS')`, which no correct harness can satisfy where /bin/bash IS 3.2. Took option B after an actual search (Zone 2.2), but with a twist the card did not anticipate: naming a single builtin and asserting it ships on bash 3.2 would repeat this card's own defect - a hardcoded belief about a platform the author cannot run. So the probe builtin is selected AT RUNTIME from bash 2.x-era candidates (shopt, caller, compgen, hash, umask) that the host itself reports as a builtin (`type -t` == builtin) with no external /usr/bin twin (`type -P` empty); on this container it picks `shopt`. 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. No skip leg: option A was not needed and a host with no qualifying builtin reddens loudly. `scripts/bump-objectui.sh` untouched.", "tests": "PLATFORM GAP, STATED FIRST: this container is Linux, bash 5.2.21. NOTHING here was run on macOS and no claim is made about it. The failing condition was CONSTRUCTED locally - a BASH_ENV file running `enable -n mapfile readarray` makes every bash the self-test spawns genuinely lack the builtin. (a) ACCEPTANCE 1: on origin/main that construction reproduces the reported symptom exactly - EXIT=1, 1 failure, `R7a ... plain= sim.out= sim.err=...mapfile: command not found`; same tree on this branch EXIT=0, all checks passed. On the plain bash-5 host: EXIT=0 both before and after. `pnpm check:objectui-changeset` (both self-tests) EXIT=0 on both host shapes. (b) ACCEPTANCE 2: injected `mapfile -t _os_bash4_regression < <(printf 'x\\n')` after `set -euo pipefail` in bump-objectui.sh; on-disk confirmed by grepping the injected marker (perl -i exits 0 on zero matches, so its status is not evidence); result R7=RED, R7b=RED status=127, R7c=RED status=127, 3 failure(s), EXIT=1 - the #12071 property survives. Restored under an EXIT trap and proven byte-identical: git hash-object == git rev-parse HEAD:scripts/bump-objectui.sh == c1ff2049c4e18585dc85d40ad4e7369a1c7ce3b9, `git status --porcelain` empty. NON-VACUITY of the new control, two mutations, each on-disk confirmed and trap-restored: (1) neutering the probe's disabling file reddens R7a on BOTH host shapes (`builtin=shopt plain=PROBE-STATUS=0 sim=PROBE-STATUS=0`) - the property the old leg could not have; (2) neutering R7b's own simulation file reddens R7a2 (`host-has-mapfile=true sim.out=MAPFILE-WORKS`) while R7b PASSES - i.e. R7a2 catches exactly the vacuous pass R7a exists to prevent. No ablation-vs-dist concern: this is a node script read from source, nothing is consumed through a package `exports`/`dist` boundary, so no rebuild leg applies. GATES: union derived at the final commit 10ddefd88a with `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` - no STALE TREE warning, change set 1 path, three-dot semantics. All 9 matched families run, exit code captured BEFORE any pipe, each gate's own verdict line quoted: agent-test-spelling EXIT=0 '0 violations - 381 file(s)'; cli-command-ids EXIT=0 '276 command-id literal(s) ... all resolve'; cross-package-test-inputs EXIT=0 'OK: 16 package(s) ... all declared'; entry-guard EXIT=0 '165 scripts/ file(s) ...'; objectui-changeset EXIT=0 'all checks passed'; parse-guard EXIT=0 '164 scripts/ file(s) ...'; pnpm-filter-targets EXIT=0 '136/173 --filter occurrence(s) ...'; check-ci-filter-parity EXIT=0 'OK: all 96 declared cross-package glob(s) (81 unique) ...'; check-cross-package-test-inputs EXIT=0 'OK: 16 package(s) ...'. check-ci-filter-parity first exited 1 with 'PREREQUISITE NOT MET - the dependency yaml is not installed', whose own text says 'Nothing was measured ... It is NOT a finding'; `pnpm install` then green. Working tree clean at 10ddefd88a. DECLARED NARROWING: the 9 static node gates were run directly, not through scripts/pm/os-verify-lock.sh - no build and no test suite among them, and the lock was held by another agent's build (391s held, 1 waiter). No repo-wide `pnpm lint` sweep; CI runs the farm exactly once regardless. skip-changeset label: the additive POST endpoint returned 403 ('GitHub access is not enabled for this session') for the whole REST surface from this seat, so the declared fallback was used - read labels, union, group write via MCP issue_write. READ-BACK confirms ['size/s','skip-changeset'].", "open_questions": [], "out_of_scope_findings": [ "NOT filed, reported here per Zone 2.4: this defect class is invisible to CI by construction. CI is ubuntu-latest with bash 5; the failure exists only where /bin/bash is 3.2, so nothing in the pipeline will ever catch the next one. The brief said to report it, not build a fix for it. #12221 (repo-wide bash-4 gate) is the adjacent lane already queued.", "NOT filed, PM assumption 2.3 CONFIRMED and understated: check:objectui-changeset is a step in .github/workflows/lint.yml, which declares NO paths: filter - it runs on every PR to main. And dispatch-gates.mjs reaches it via pendingChangesetFamilies, the changeset-directory probe, so every card that writes a changeset derives it. Not 'a broad set of paths': effectively every card in the repo.", "NOT filed, mechanism nuance the card could not have known: on a genuinely builtin-less host, reintroducing a bash-4 builtin into bump-objectui.sh aborts the self-test EARLIER than R7b - an uncaught execFileSync throw at digest line 1516, since every leg there already runs on a mapfile-less shell. Still a loud red naming the exact cause, but not R7b's assertion. Verified PRE-EXISTING by replaying the mutation against origin/main's own digest: identical abort, same line. Not introduced by this change and not a defect worth a card on its own." ] }Generated by Claude Code
Generated by Claude Code
yinlianghui commentedon Aug 25, 2026
os-dev-report
{ "issue": 12254, "status": "done", "branch": "claude/issue-12254-r7a-control-on-bash32-host", "pr": "https://github.com/objectstack-ai/objectstack/pull/12298", "premise_still_valid": true, "summary": "The card's account of the mechanism was verified against the code and is exactly right: R7a ran a `mapfile` probe plain and simulated and asserted `probePlain.stdout.includes('MAPFILE-WORKS')`, which no correct harness can satisfy where /bin/bash IS 3.2. Took option B after an actual search (Zone 2.2), but with a twist the card did not anticipate: naming a single builtin and asserting it ships on bash 3.2 would repeat this card's own defect - a hardcoded belief about a platform the author cannot run. So the probe builtin is selected AT RUNTIME from bash 2.x-era candidates (shopt, caller, compgen, hash, umask) that the host itself reports as a builtin (`type -t` == builtin) with no external /usr/bin twin (`type -P` empty); on this container it picks `shopt`. 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. No skip leg: option A was not needed and a host with no qualifying builtin reddens loudly. `scripts/bump-objectui.sh` untouched.", "tests": "PLATFORM GAP, STATED FIRST: this container is Linux, bash 5.2.21. NOTHING here was run on macOS and no claim is made about it. The failing condition was CONSTRUCTED locally - a BASH_ENV file running `enable -n mapfile readarray` makes every bash the self-test spawns genuinely lack the builtin. (a) ACCEPTANCE 1: on origin/main that construction reproduces the reported symptom exactly - EXIT=1, 1 failure, `R7a ... plain= sim.out= sim.err=...mapfile: command not found`; same tree on this branch EXIT=0, all checks passed. On the plain bash-5 host: EXIT=0 both before and after. `pnpm check:objectui-changeset` (both self-tests) EXIT=0 on both host shapes. (b) ACCEPTANCE 2: injected a `mapfile -t _os_bash4_regression` line after `set -euo pipefail` in bump-objectui.sh; on-disk confirmed by grepping the injected marker (perl -i exits 0 on zero matches, so its status is not evidence); result R7=RED, R7b=RED status=127, R7c=RED status=127, 3 failure(s), EXIT=1 - the #12071 property survives. Restored under an EXIT trap and proven byte-identical: git hash-object == git rev-parse HEAD:scripts/bump-objectui.sh == c1ff2049c4e18585dc85d40ad4e7369a1c7ce3b9, `git status --porcelain` empty. NON-VACUITY of the new control, two mutations, each on-disk confirmed and trap-restored: (1) neutering the probe's disabling file reddens R7a on BOTH host shapes (`builtin=shopt plain=PROBE-STATUS=0 sim=PROBE-STATUS=0`) - the property the old leg could not have; (2) neutering R7b's own simulation file reddens R7a2 (`host-has-mapfile=true sim.out=MAPFILE-WORKS`) while R7b PASSES - i.e. R7a2 catches exactly the vacuous pass R7a exists to prevent. No ablation-vs-dist concern: this is a node script read from source, nothing is consumed through a package `exports`/`dist` boundary, so no rebuild leg applies. GATES: union derived at the final commit 10ddefd88a with `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` - no STALE TREE warning, change set 1 path, three-dot semantics. All 9 matched families run, exit code captured BEFORE any pipe, each gate's own verdict line quoted: agent-test-spelling EXIT=0 '0 violations - 381 file(s)'; cli-command-ids EXIT=0 '276 command-id literal(s) ... all resolve'; cross-package-test-inputs EXIT=0 'OK: 16 package(s) ... all declared'; entry-guard EXIT=0 '165 scripts/ file(s) ...'; objectui-changeset EXIT=0 'all checks passed'; parse-guard EXIT=0 '164 scripts/ file(s) ...'; pnpm-filter-targets EXIT=0 '136/173 --filter occurrence(s) ...'; check-ci-filter-parity EXIT=0 'OK: all 96 declared cross-package glob(s) (81 unique) ...'; check-cross-package-test-inputs EXIT=0 'OK: 16 package(s) ...'. check-ci-filter-parity first exited 1 with 'PREREQUISITE NOT MET - the dependency yaml is not installed', whose own text says 'Nothing was measured ... It is NOT a finding'; `pnpm install` then green. Working tree clean at 10ddefd88a. DECLARED NARROWING: the 9 static node gates were run directly, not through scripts/pm/os-verify-lock.sh - no build and no test suite among them, and the lock was held by another agent's build (391s held, 1 waiter). No repo-wide `pnpm lint` sweep; CI runs the farm exactly once regardless. skip-changeset label: the additive POST endpoint returned 403 ('GitHub access is not enabled for this session') for the whole REST surface from this seat, so the declared fallback was used - read labels, union, group write via MCP issue_write. READ-BACK confirms ['size/s','skip-changeset'].", "open_questions": [], "out_of_scope_findings": [ "NOT filed, reported here per Zone 2.4: this defect class is invisible to CI by construction. CI is ubuntu-latest with bash 5; the failure exists only where /bin/bash is 3.2, so nothing in the pipeline will ever catch the next one. The brief said to report it, not build a fix for it. #12221 (repo-wide bash-4 gate) is the adjacent lane already queued.", "NOT filed, PM assumption 2.3 CONFIRMED and understated: check:objectui-changeset is a step in .github/workflows/lint.yml, which declares NO paths: filter - it runs on every PR to main. And dispatch-gates.mjs reaches it via pendingChangesetFamilies, the changeset-directory probe, so every card that writes a changeset derives it. Not 'a broad set of paths': effectively every card in the repo.", "NOT filed, mechanism nuance the card could not have known: on a genuinely builtin-less host, reintroducing a bash-4 builtin into bump-objectui.sh aborts the self-test EARLIER than R7b - an uncaught execFileSync throw at digest line 1516, since every leg there already runs on a mapfile-less shell. Still a loud red naming the exact cause, but not R7b's assertion. Verified PRE-EXISTING by replaying the mutation against origin/main's own digest: identical abort, same line. Not introduced by this change and not a defect worth a card on its own.", "NOT filed, seat-infrastructure observation for the PM: the entire github.com REST surface returns 403 'GitHub access is not enabled for this session' from this dev seat (PR creation, label POST, api.github.com generally), while git push and the MCP github tools both work. The os-dev contract's label step is written around the additive REST endpoint, which is unreachable here; every dev on this container will hit the same wall and need the declared read-union-write fallback." ] }Generated by Claude Code
Generated by Claude Code