ci: run the launcher regression suite on the Linux leg only (CI-07 slice) - #2608
ci: run the launcher regression suite on the Linux leg only (CI-07 slice)#2608Chris0Jeky wants to merge 4 commits into
Conversation
The suite launches real PowerShell/API/Vite processes and produced six false reds on unrelated heads on hosted windows-latest. SC-3 puts hosted minutes on Linux only, so gate the step to runner.os == 'Linux' and keep Windows lint/typecheck/build/coverage exactly as they were. Adds a placement contract test picked up by the existing smart-ci self-test glob.
Names the local Windows command that replaces the hosted PowerShell launcher evidence under CI-07 #2331 / SC-3.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Review (agent half of the ADR-0066 gate; Codex credits exhausted, SC-9). One fresh-context reviewer (read-only, Opus 5) at exact head 6d9a0f8: verdict SHIP, no CRITICAL/HIGH. This PR is CI-control ( Confirmed: the workflow change is exactly two added lines (a comment and Red-first evidence recorded on the PR: the placement test failed on the unmodified workflow ( Findings, all non-blocking, most of them decision points for the maintainer's SC-10 review rather than defects in the diff:
Trade-off, stated plainly: hosted PowerShell launcher evidence disappears from every PR (it was the source of eight false reds on unrelated heads in about six hours on 2026-09-05, measured at 6m35s of Merge gate: maintainer review (SC-10) plus hosted Workflow Lint, |
|
Cross-reference: the beta lane's measurement on #2378 (2026-09-05) concludes that this PR is the disposition for #2378 as well: every ETIMEDOUT and job-cancellation occurrence recorded there is on the Windows leg, where the launcher suite runs 3 to 5 times slower under runner contention and a per-spawn budget change would only move the failure to a job cancellation. The SC-10 ruling on this PR therefore carries #2378's payoff. |
Summary
One bounded CI-07 slice: the source launcher regression suite (
scripts/ci/dev-up.test.mjs) now runson the Linux leg of
Frontend Unitonly..github/workflows/reusable-frontend-unit.yml: theRun source launcher regression suitestep gainsif: runner.os == 'Linux'. Itsrunline, itstimeout-minutes: 10and the#2378comment above itare unchanged. A two line comment records
#2331, SC-3 and the reason.validation and the coverage-threshold Vitest run exactly as today, and
Frontend Unit (windows-latest)stays a required context.
ci-required.yml,ci/policy.v1.json,scripts/dev-up.*andscripts/ci/dev-up.test.mjsare untouched.scripts/ci/smart-ci/launcher-suite-placement.test.mjspins the placement: thelauncher step still runs
dev-up.test.mjs, its condition is exactlyrunner.os == 'Linux', the matrixstill contains both
ubuntu-latestandwindows-latestso the Windows leg cannot be silently removed,and lint, typecheck, build and coverage carry no OS condition.
docs/TESTING_GUIDE.md: thefrontend-unitentry under## CI Gatesnow states the Linux-onlyplacement and the local Windows command that replaces the hosted PowerShell evidence.
Root cause
The suite launches real PowerShell and Bash launchers and their API and Vite children. On hosted
windows-latestthose process trees leak or stall, and the step fails on heads that changed nothing nearit. Because the step sits before the frontend steps, a failure also skips install, lint, typecheck, build,
PWA worker validation, coverage and the bundle check, so one launcher stall costs the whole Windows leg.
Six reds on unrelated heads in about five hours on 2026-09-05, recorded on
#2378,#2561,#1898and#2588. Failing cases seen:pipeline cancellation runs transactional cleanup from finallywithspawnSync ETIMEDOUT,
Vite fallback leaves the foreign frontend-port owner alive, andinvalid Vite outcome late cleans both trees and never reports success.#2575#2575#2590#2593#2586#2588)The last row is the one case this change does NOT remove. It is a Linux failure and stays fully visible
on the Linux leg.
This is the change proposed on
#2331on 2026-09-04, under the maintainer's SC-3 re-ruling of2026-09-03 (
OUTSTANDING_TASKS.md, ADR-0066 amendment): hosted minutes are Linux-only and Windowsevidence runs locally, on the CI-04
#2328laptop runner once it is registered and as agent-run provingchecks until then.
What is lost, what replaces it, minutes saved
Lost: hosted PowerShell launcher evidence on every PR. The
dev-up.ps1cases no longer run in CI at alluntil CI-04 lands, so a PowerShell-only launcher regression can now reach
mainunobserved. The Bashlauncher cases and every platform-independent case keep running on the Linux leg on every PR.
Replaced by: the local Windows command, run from the repository root, now named in
docs/TESTING_GUIDE.md:and, later, the CI-04
#2328laptop runner.Minutes saved, measured from job 101222450626 (
#2575, run 33935478869): the step ran 01:13:37Z to01:20:12Z, that is 6m35s of
windows-latestwall clock, and failed. The#2378comment in the workflowrecords a passed
windows-latestrun of the same step at 6m31s, so about 6.5 minutes of Windows wallclock per PR either way. The conversion from wall clock to billed allowance minutes under
private-repository accounting was not re-measured for this PR.
Verification
All commands run from the worktree root on Windows.
Red first, against the unmodified workflow, before the
ifwas added:tests 3, pass 2, fail 1. The failing assertion was
the launcher step must be gated to the Linux leg,actual: null,expected: "runner.os == 'Linux'".Green after the workflow change: same command, tests 3, pass 3, fail 0.
tests 94, pass 94, fail 0 (91 before this PR plus the 3 new ones).
tests 277, pass 263, fail 12, cancelled 2, duration 540s. This is NOT green on this box, and it was not
green before this PR either. All 12 failures are local environment failures in two files that this PR does
not touch and that read none of the files it changes:
scripts/ci/actionlint-bootstrap.test.mjs, all failing onAssertionError: BASH_BIN must point to the installed tool. Actionlint is not installed here(
actionlint --versionreportscommand not found). That file readsci-extended.yml, notreusable-frontend-unit.yml.scripts/ci/dev-up.test.mjs, every one of them aBash:launcher case timing out at 50s, 59s or97s under Git Bash on Windows. This is the known local
#2378cohort, the same cohort recorded indocs/STATUS.mdfor PR#2548. That file reads no workflow; its only mention ofreusable-frontend-unit.ymlis a comment about the step timeout.No control run at the base commit was performed. It would have been byte-identical: both failing files are
unmodified by this PR and neither reads the workflow, the new test or the guide.
Docs governance check passed.no output.
Job step timings were read from the GitHub API for the two jobs quoted above: 101222450626
(
windows-latest, launcher step failure, 6m35s, all later frontend steps skipped) and 101222860762(
ubuntu-latest, launcher step failure, 47s).actionlint --versionreportscommand not foundon this box and no vendored binary exists in the tree,so the hosted
Workflow Lintjob in CI Extended is the proof for the YAML change, not a local run.Not verified
Workflow Lint,Smart CI / Planner Self-Testandci-requiredat this exact head are unobserved atthe time of writing.
node --test scripts/ci/*.test.mjson this box. 12 pre-existing environment failuresremain, itemised above, and none of them were fixed or investigated further here. Notably the local
Bash:launcher failures are the same class of instability this PR removes from hosted Windows, whichis corroboration for the change and not evidence produced by it.
dotnetand no Vitest or Playwright run applies andnone was performed.
recorded on the issues; two of them were confirmed directly against the API, the rest were not
re-fetched.
completes lint, typecheck, build, PWA worker and coverage green with the launcher step skipped.
Risk notes
.claude/rules/ci-control.mdand ADR-0066. Openedready-for-review and parked for the maintainer under SC-10. I do not merge it.
regression is now invisible to CI until CI-04
#2328registers the laptop runner. The new contract testand the TESTING_GUIDE paragraph exist so this is a recorded, reversible trade rather than silent drift.
if:from the step. The contract test would then fail and name thereason, which is intended.
Frontend Unit (windows-latest)still runs and still reports, so no required context disappears andbranch protection needs no change. The new test asserts the matrix keeps both legs precisely so a later
change cannot quietly drop the Windows leg while claiming this precedent.
scripts/ci/smart-ci/rather thanscripts/ci/so the existingnode --test scripts/ci/smart-ci/*.test.mjsglob insmart-ci-self-test.ymlpicks it up with noworkflow edit.
scripts/ci/*.test.mjshas no glob runner, so a file there would have been wired intonothing. The sibling workflow-contract test
required-e2e-dependencies.test.mjsalready lives in thatdirectory.
Refs #2331