Skip to content

fix(scripts): make the three host-dependent scripts/__tests__ files run on a stock macOS host - #8511

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-8404-macos-host-dependent-tests
Sep 8, 2026
Merged

fix(scripts): make the three host-dependent scripts/__tests__ files run on a stock macOS host#8511
baozhoutao merged 1 commit into
mainfrom
claude/issue-8404-macos-host-dependent-tests

Conversation

@claude

@claude claude Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #8404

Three files under scripts/__tests__ passed on Linux CI and failed on a stock macOS host on byte-identical bytes. None of the four assertions was about the tree; each read a host command or a host behaviour. All three are repaired at the end that is actually wrong, and none is skipped, disabled, quarantined or weakened.

Re-derivation before the fix

⚠️ This container is Linux and no macOS host was available, so the reported reds were not reproduced directly. Each claim below was established from the code plus a local discriminator that needs no macOS; where a claim could not be established that way it is stated as unverified rather than guessed.

  • The three files are still byte-identical to origin/main (f08d1a86a): blobs d8e51c6c0, 9624b91d6, a52bec87d match origin/main exactly. The card's measured head 21b1bf51f is no longer an object in this repository, so the comparison is against origin/main as it stands.
  • bash32-floor-wiring. The failing assertion runs check-bash32-floor.mjs --self-test. Its ⭐ and the probes are real shell battery runs bash -n over every row of CONSTRUCTS, and every row is by declaration a construct above the bash 3.2 floor this gate declares. The card's three syntax errors — a brace, an ampersand, a redirect — line up one-for-one and with nothing left over against the three parse-level 4.0 rows: coproc CO { cat; }, echo a |& cat, echo hi &>> /dev/null. Two further legs have the same premise and are named in the diff: the [[ -v ]] parse case (this file already records that bash -n judges [[ operators) and the mapfile simulated-3.2 harness, which needs a host that HAS mapfile to remove.
  • check-control-bytes. expect(declined.stdout).toBe('') is the only host-dependent line. The discriminator is not the platform, it is which stream grep writes its refusal to, so a grep that writes the BSD spelling to stdout reproduces it exactly. Demonstrated here on Linux with a shim first on PATH.
  • ensure-chromium-ready. timeout is GNU coreutils. Demonstrated on Linux under a PATH where timeout and gtimeout are genuinely absent, against origin/main's own script: exit 1, the dependency-install marker never created, install-deps never reached. That is a defect in the script, not only in its test — the bound did not go missing, the call failed at 127 before the recovery could recover.

What changed

scripts/check-bash32-floor.mjs — the gate, not the test that runs it. A floor gate whose battery cannot run on the floor it declares is a gate asserting something it has never demonstrated. --self-test now states that premise, detects it by capability (one bash-4 operator and one bash-4 builtin — never a platform name), and narrows exactly the cases a host below the floor cannot judge. A narrowing is a real coverage loss, so it is printed per case, counted, and carried in the verdict line. ⛔ The scan is untouched and never narrowed: it is pure JS and judges a 3.2 host exactly as it judges CI. A new battery pins the mechanism in both directions, refuses a platform-name branch on any code line, and requires the two capability probes to be constructs this gate's own table declares above the floor.

scripts/__tests__/check-control-bytes.test.ts. The search outage is "grep printed no line of the file", and the refusal itself is already pinned by refusedAsBinary beside it. The assertion is now written against matching lines rather than against an empty stdout, and a shim standing in for BSD grep pins the other userland here, on Linux, on every run.

scripts/ensure-chromium-ready.sh. run_bounded resolves timeout, then gtimeout, then bounds the call from bash itself and reports the same 124 either way. ⛔ There is no fourth branch that runs the command unbounded. The fallback is bash 3.2 clean, as this repo's own floor gate requires, and check:bash32-floor is green on it.

Non-vacuity — four ablations, each proved on disk and restored by state

Every leg mutated one file, proved the mutation reached disk by blob hash and marker count before reading any result, ran under an EXIT INT TERM trap with absolute paths, and was restored with git checkout HEAD -- PATH, proven by git diff HEAD being empty. Full logs are in the run.

ablation stimulus result
A one CONSTRUCTS probe made unparseable (coproc CO { cat; } to coproc CO { cat; ;}), blob 539666d3c to e711fca4a self-test exit 1, ✗ coproc: the probe is shell a bash-4 parser accepts — the preserved leg still fails when broken
B the capability probe made unparseable, blob 539666d3c to db03ee0e7 self-test exit 0, 24 narrowed, verdict 136 cases pass, 24 NARROWED; the wiring test is green (9 passed) — the macOS branch, end to end
C the repaired grep assertion put back to toBe(''), blob d04cc4775 to ff3b125f7 the BSD-userland case goes red (1 failed / 37 passed) — the macOS failure, reproduced on Linux
D run_bounded reverted to a bare timeout, blob f235f5377 to 432e35b90 the two no-timeout cases go red (2 failed / 7 passed), the GNU cases stay green

Paired control, same stimulus on both trees. Three probes made unparseable — which is what a bash 3.2 host does to them: on origin/main's gate, self-test exit 1, 3 failing cases of 155. On this branch's gate with the same three plus the capability probe a floor host also refuses, self-test exit 0, 136 cases pass, 24 NARROWED, 0 failing.

Verification

command verdict
pnpm exec vitest run scripts/__tests__/ Test Files 121 passed (121) · Tests 3634 passed (3634) (the card's own population; 52 to 56 tests across the three files, +4 new)
node scripts/check-bash32-floor.mjs --self-test ✓ check-bash32-floor self-test: 160 cases pass. (155 before; +5 new cases)
node scripts/check-bash32-floor.mjs ✓ ... 12 tracked shell file(s) ... name no bash 4+ construct
node scripts/check-control-bytes.mjs ✅ check-control-bytes: OK (scanned 6724 tracked text file(s); skipped 85 binary)
node scripts/check-changeset-presence.mjs ✅ No source or published contract of a released package changed in this range, so no changeset is owed. — run, not guessed; no changeset is added
node scripts/check-governed-queue-guard.mjs --test (4 paths) ✅ NOT GOVERNED — 4 path(s) checked against 5 governed surface(s); none matched.
pnpm exec tsc -p tsconfig.scripts.json exit 0
pnpm lint:root exit 0, ✖ 32 problems (0 errors, 32 warnings) — full root scope, no narrowing; none of the 32 is in a changed file
grep -naP control-byte self-scan over the four changed files no match

Heavy runs went through the shared verify lock and the wrapper's own VERDICT command-exit line was read, never a bare $?.

Limits, stated rather than discovered later

  • ⚠️ Not verified on a real bash 3.2. The egress policy denies ftp.gnu.org and cross-owner GitHub repositories, so no bash 3.2 could be obtained or built here. Ablation B simulates a floor host by making the capability probe unparseable, which is exactly what a 3.2 parser does to it, but it is a simulation.
  • ⚠️ The EPOCHSECONDS legs are left un-narrowed on reasoning, not measurement. On bash 3.2 the variable is genuinely absent, so unset plus set -u should produce the same unbound failure those two cases assert. If a macOS seat still sees them red, that is the one remaining leg and it narrows the same way in one line.
  • ⚠️ On a host below the floor, 24 self-test cases do not run. That is a stated coverage loss, not a hidden one: CI runs bash 5 and runs them all, and the production scan is unaffected on every host.
  • finding(types): the handler-keys-string-any-mirrors-7344 census is host-dependent — git grep -E has no \b on macOS (BSD regex), so all five assertions go red locally while CI is green #8361 was not touched. Triage drew that boundary explicitly: same class, different package, its own card.

🤖 Generated with Claude Code


Generated by Claude Code

… run on a stock macOS host

Three files in `scripts/__tests__` passed on Linux CI and failed on a stock
macOS host on byte-identical bytes. None of the four assertions was about the
tree; each read a host command or a host behaviour.

check-bash32-floor `--self-test` — the sharpest of the three, and fixed in the
GATE rather than in the test that runs it. Every probe, harness and `bash -n`
leg drives a bash-4+ construct through the host's own bash, and the host this
gate exists for is macOS: bash 3.2.57, where `coproc`/`|&`/`&>>` are syntax
errors, `mapfile` is not a builtin there is anything to disable, and `[[ -v ]]`
is a conditional operator `bash -n` also refuses. A floor gate whose battery
cannot run on the floor it declares is a gate asserting something it has never
demonstrated. The self-test now states that premise, detects it by CAPABILITY
(a bash-4 operator and a bash-4 builtin, never a platform name), and narrows
exactly those cases where the host cannot judge them — counted, printed per
case, and carried in the verdict line, because a narrowing is a real coverage
loss. The SCAN is untouched and is not narrowed: it is pure JS and judges a 3.2
host exactly as it judges CI.

check-control-bytes — `expect(declined.stdout).toBe('')` asserted one userland's
way of reporting a refusal rather than the refusal. GNU grep >= 3.5 writes
`grep: <f>: binary file matches` to stderr and leaves stdout empty; BSD grep
writes `Binary file <f> matches` to stdout. Both refuse and both print no line
of the file, which is the search outage the case is about, so the assertion is
now written against matching lines. A shim first on PATH pins the BSD reading
here on Linux.

ensure-chromium-ready.sh — a bare `timeout` is GNU coreutils, and a stock macOS
host has neither it nor Homebrew's `gtimeout`. The bound did not merely go
missing there: the call failed at 127 before `install-deps` ran, so the recovery
path could not recover. `run_bounded` resolves `timeout`, then `gtimeout`, then
bounds the call from bash itself (bash 3.2 clean, as this repo's floor requires)
and reports the same 124 either way. Two cases run under a PATH where both
binaries are genuinely absent, with a control that proves they are.

⛔ Nothing is skipped, disabled or quarantined, and no assertion is weakened to
accommodate a host: the GNU paths are still measured by the same cases on the
same run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
@claude

claude Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Dequeued 04:48:06Z on a failure this diff cannot reach; re-queued 06:31:07Z — the one re-queue this PR gets. domain:devx @ objectui execution seat, PM session session_01FhBNJcLRZLe8M87VcUgpKr, R46.

github-merge-queue[bot] removed this PR at 04:48:06Z. The group's Test (shard 2/4) failed on:

FAIL packages/plugin-kanban/src/ObjectKanban.contractEnvelope-6839.test.tsx:134
     ObjectKanban — the find() envelope it reads (objectui#6839)
       > still reads the contract's `data` member
     AssertionError: the declared rows member must still draw both cards: expected +0 to be 2
Test Files  1 failed | 677 passed (678)
Tests       1 failed | 9026 passed (9027)

⛔ Not this PR's, settled structurally rather than by counting

This diff is scripts/check-bash32-floor.mjs, scripts/ensure-chromium-ready.sh, scripts/__tests__/check-control-bytes.test.ts and scripts/__tests__/ensure-chromium-ready.test.ts. None of them can reach plugin-kanban's render path — no import, no fixture, no config that module loads. The failing assertion counts kanban cards drawn from a { data: [...] } envelope.

⚠️ That is deliberately not the argument "it failed elsewhere too". This seat wrote a frequency rule earlier today ("two failures on the same head is a property of that head"), acted on it, and had to retract a correct attribution and then withdraw the retraction. Frequency is not evidence of ownership; reachability is.

objectui#8493 has now dequeued three PRs whose diffs cannot reach it: #8462 (two comment blocks), #8486 (a TZ pin in vitest.config.mts), and this one (shell-gate scripts). It is a required check taxing arbitrary lanes, and its mechanism is documented on that card — cardsThrough never waits on the rows it asserts about, so the failure is always the file's first it(), the one paying the cold useSettledSchema / MetadataCache settle. ⛔ The repair lands in plugin-kanban or @object-ui/core; ⛔ neither is this lane's.

What happens next, stated in advance so it is not a judgement call later

Re-queued once, at 06:31:07Z. ⛔ If it is dequeued a second time on the same case, this PR stops there — no third attempt. This seat will say so on objectui#8493 rather than keep re-queueing, because a required check that dequeues on a case no diff can reach is that card's problem to fix, not something to out-wait.

⛔ Nothing about this branch changes meanwhile: no rebase, no force-push, no edit. The head that was green on 28 checks is the head that is queued.


Generated by Claude Code

@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Sep 8, 2026
@claude

claude Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Dequeued a second time on the same case ⇒ this PR stops here, exactly as committed above. domain:devx @ objectui execution seat, PM session session_01FhBNJcLRZLe8M87VcUgpKr, R47, 2026-09-08T07:15Z.

The reading, from the job logs rather than from the field

attempt queued removed run / job failing case
1 04:32:45Z 04:48:06Z run 34187386581, job 101938355306 ObjectKanban.contractEnvelope-6839.test.tsx:134, expected +0 to be 2
2 06:31:07Z 06:47:15Z run 34195031188, job 101960778352 same file, same line, same numbers

Both logs read Test Files 1 failed | 677 passed, Tests 1 failed | 9026 passed — ⇒ the shard is otherwise entirely green, and the one red case is the one objectui#8493 exists for. ⛔ The second attempt was not a different failure and not a different case.

Why this is not this PR's failure, argued structurally

The case failed at 2026-09-08T01:09:52Z on PR #8462 — a diff of two comment blocks — before this branch was ever queued. A defect that predates a diff cannot have been introduced by it. That row alone settles it; the supporting reading is that this PR's four files are all under scripts/ (check-bash32-floor.mjs, ensure-chromium-ready.sh, and those two files' own tests), and ⛔ none of them is imported by packages/plugin-kanban, by @object-ui/core, or by the dom setup the failing case runs under.

⇒ Attribution here is structural — whether the diff can reach the failing code — ⛔ not a count of failures.

What this seat did, and did not do

  • No third re-queue. The commitment was written before the second attempt precisely so that this decision would not be re-argued after seeing the result.
  • This PR stays open and stays ready, auto_merge off and ⛔ not re-armed. Nothing about it needs changing; it is green on its own branch.
  • Its card objectui#8404 moves pm:dispatchedpm:blocked with Blocked-by: #8493 in the body, assignee retained — the state-model's work finished, PR held by an external gate case.
  • The escalation is recorded on objectui#8493 (comment 5580826266): five red runs across three PRs, four merge-queue removals, ≈31 minutes of shared queue time from these two attempts alone.

What unblocks it

objectui#8493 landing its repair — the patch shape is already written there (wait on the rows each arm asserts about, ⛔ without collapsing the negative arm into a tautology). That work is domain:ui, ⛔ not this seat's lane. When it lands, this PR needs only a re-queue; ⛔ no change to its diff is anticipated.


Generated by Claude Code

@claude

claude Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

The blocker was repaired on main, so this PR is re-queued — and this seat is explicit that it is walking back its own "no third attempt". domain:devx @ objectui execution seat, PM session session_01FhBNJcLRZLe8M87VcUgpKr, R47, 2026-09-08T08:20Z.

What changed, measured on a re-fetched origin/main

PR #8533 merged at 07:58:29Z as 90a9aab32test(plugin-kanban): split the contractEnvelope-6839 waits by expected outcome, closing objectui#8532. Read on origin/main:

90a9aab32  test(plugin-kanban): split the contractEnvelope-6839 waits by expected outcome (#8533)

⭐ And it is the right repair, not merely a green one. The failing case now carries an explicit outcome type:

type Outcome =
  /** Wait FOR the rows. `because` is carried into the timeout message. */
  | { readonly draws: number; readonly because: string }
  /** No absence to wait for: settle, then read. */
  | { readonly refuses: true };

⇒ The positive arms wait on the rows they assert about, and the negative arm still asserts zero after a settle signal that is ⛔ not derived from the card count. That is precisely the shape objectui#8493 prescribed at 03:22Z, including the warning that a naive "wait for cards > 0" would make the refusing arm unfalsifiable. ⚠️ The PR also corrects the mechanism this seat relayed: the gate is React.lazy(() => import('./KanbanImpl')) behind a Suspense, ⛔ not useSettledSchema warmth — the header is absent until that chunk resolves.

⚠️ The commitment this seat wrote, and why re-queueing is not a quiet breach of it

Written here before the second attempt:

If it is dequeued a second time on the same case, this PR stops there — no third attempt. This seat will say so on objectui#8493 rather than keep re-queueing, because a required check that dequeues on a case no diff can reach is that card's problem to fix, not something to out-wait.

⭐ The clause after because is the whole content of the promise: ⛔ do not spend the shared queue re-rolling dice against a defect someone else has to fix. That defect is now fixed. Re-queueing against a repaired main is a different act from a third roll against the same wall — but the literal sentence says "no third attempt", so this seat states the reversal in full rather than letting the action speak for it. ⚠️ ⛔ Anyone reading this later should hold this seat to the stated reason, not to a re-reading that makes the reversal look automatic.

State at re-queue

  • Head 7ee049d51: 27 checks completed success, 3 skipped, 0 failures (read 08:18Z).
  • Card objectui#8404 returns from pm:blocked to pm:dispatched; its Blocked-by: #8493 body line stays as the historical record of why it waited.
  • objectui#8493 itself is still open — it may be a duplicate of the now-closed objectui#8532, but that is the domain:ui seat's ruling to make, ⛔ not this seat's. The corroboration is posted there.

⚠️ If this PR is dequeued again on that same case, the case is not repaired and that is a new fact about 90a9aab32, ⛔ not a third roll — it would go straight back to objectui#8493 with the run id.


Generated by Claude Code

@baozhoutao
baozhoutao added this pull request to the merge queue Sep 8, 2026
Merged via the queue into main with commit 96cf3d2 Sep 8, 2026
31 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-8404-macos-host-dependent-tests branch September 8, 2026 08:37
@claude

claude Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

LANDED — 96cf3d2ac on origin/main. domain:devx @ objectui execution seat, PM session session_01FhBNJcLRZLe8M87VcUgpKr, R47, 2026-09-08T08:52Z. PR #8511 (card objectui#8404), merged on the third queue attempt — the first that ran against a main carrying objectui#8493's repair.

The re-queue decision is now measured, not argued. This PR was dequeued twice on a defect its diff cannot reach; the third attempt, on a base carrying 90a9aab32, merged with 28 completed success, 3 skipped, 0 failures. ⇒ The attribution written on this PR at 07:15Z — structural, not statistical — held: nothing about the diff changed between attempt two and attempt three.

Landing probe, on a re-fetched origin/main (19d86fe9e)

probe expect read
HOST_PROBES in scripts/check-bash32-floor.mjs > 0 6
SELF_TEST_BATTERY_FLOOR in the same file > 0 3
run_bounded in scripts/ensure-chromium-ready.sh > 0 3
there is no fourth branch — the fence forbidding an unbounded fallback > 0 1
firing controlbash in the same shell script, same command shape > 0 8
nonsense controlzzq-not-a-real-token-8404 0 0

⇒ The zero is a reading: the same command returns 8 on a term that is certainly there.

What is now on main

The three host-dependent scripts/__tests__ files run on a stock macOS host, and — the part that matters more than the portability — the gate was fixed rather than the test. Capability is detected by probing the host (echo a |& cat for the grammar, mapfile -t x < /dev/null for the builtin) instead of by platform name, the narrowing is pinned in both directions, and run_bounded resolves timeoutgtimeout → a bash-only bound with the fence "there is no fourth branch that runs the command unbounded" written into the file.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants