Skip to content

ci: run the launcher regression suite on the Linux leg only (CI-07 slice) - #2608

Open
Chris0Jeky wants to merge 4 commits into
mainfrom
issue-2331/launcher-suite-linux-only
Open

ci: run the launcher regression suite on the Linux leg only (CI-07 slice)#2608
Chris0Jeky wants to merge 4 commits into
mainfrom
issue-2331/launcher-suite-linux-only

Conversation

@Chris0Jeky

Copy link
Copy Markdown
Owner

Summary

One bounded CI-07 slice: the source launcher regression suite (scripts/ci/dev-up.test.mjs) now runs
on the Linux leg of Frontend Unit only.

  • .github/workflows/reusable-frontend-unit.yml: the Run source launcher regression suite step gains
    if: runner.os == 'Linux'. Its run line, its timeout-minutes: 10 and the #2378 comment above it
    are unchanged. A two line comment records #2331, SC-3 and the reason.
  • Nothing else in the workflow changes. The Windows leg keeps lint, typecheck, build, the PWA worker
    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.* and
    scripts/ci/dev-up.test.mjs are untouched.
  • New contract test scripts/ci/smart-ci/launcher-suite-placement.test.mjs pins the placement: the
    launcher step still runs dev-up.test.mjs, its condition is exactly runner.os == 'Linux', the matrix
    still contains both ubuntu-latest and windows-latest so the Windows leg cannot be silently removed,
    and lint, typecheck, build and coverage carry no OS condition.
  • docs/TESTING_GUIDE.md: the frontend-unit entry under ## CI Gates now states the Linux-only
    placement 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-latest those process trees leak or stall, and the step fails on heads that changed nothing near
it. 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, #1898 and
#2588. Failing cases seen: pipeline cancellation runs transactional cleanup from finally with
spawnSync ETIMEDOUT, Vite fallback leaves the foreign frontend-port owner alive, and
invalid Vite outcome late cleans both trees and never reports success.

PR Run Job Leg
#2575 33926387119 windows-latest
#2575 33935478869 101222450626 windows-latest
#2590 33936200692 101224507881 windows-latest
#2593 33936709076 101225941642 windows-latest
#2586 33935622081 101222860762 ubuntu-latest (#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 #2331 on 2026-09-04, under the maintainer's SC-3 re-ruling of
2026-09-03 (OUTSTANDING_TASKS.md, ADR-0066 amendment): hosted minutes are Linux-only and Windows
evidence runs locally, on the CI-04 #2328 laptop runner once it is registered and as agent-run proving
checks until then.

What is lost, what replaces it, minutes saved

Lost: hosted PowerShell launcher evidence on every PR. The dev-up.ps1 cases no longer run in CI at all
until CI-04 lands, so a PowerShell-only launcher regression can now reach main unobserved. The Bash
launcher 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:

node --test --test-concurrency=1 --test-timeout=30000 scripts/ci/dev-up.test.mjs

and, later, the CI-04 #2328 laptop runner.

Minutes saved, measured from job 101222450626 (#2575, run 33935478869): the step ran 01:13:37Z to
01:20:12Z, that is 6m35s of windows-latest wall clock, and failed. The #2378 comment in the workflow
records a passed windows-latest run of the same step at 6m31s, so about 6.5 minutes of Windows wall
clock 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 if was added:

node --test scripts/ci/smart-ci/launcher-suite-placement.test.mjs

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.

node --test scripts/ci/smart-ci/*.test.mjs

tests 94, pass 94, fail 0 (91 before this PR plus the 3 new ones).

node --test scripts/ci/*.test.mjs

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:

  • 4 in scripts/ci/actionlint-bootstrap.test.mjs, all failing on
    AssertionError: BASH_BIN must point to the installed tool. Actionlint is not installed here
    (actionlint --version reports command not found). That file reads ci-extended.yml, not
    reusable-frontend-unit.yml.
  • 8 in scripts/ci/dev-up.test.mjs, every one of them a Bash: launcher case timing out at 50s, 59s or
    97s under Git Bash on Windows. This is the known local #2378 cohort, the same cohort recorded in
    docs/STATUS.md for PR #2548. That file reads no workflow; its only mention of
    reusable-frontend-unit.yml is 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.

node scripts/check-docs-governance.mjs

Docs governance check passed.

git diff --check

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 --version reports command not found on this box and no vendored binary exists in the tree,
so the hosted Workflow Lint job in CI Extended is the proof for the YAML change, not a local run.

Not verified

  • Hosted-only qualification is the R4 proof for a CI-control change and it was not observed here:
    Workflow Lint, Smart CI / Planner Self-Test and ci-required at this exact head are unobserved at
    the time of writing.
  • Local actionlint. Not installed, see above.
  • A fully green node --test scripts/ci/*.test.mjs on this box. 12 pre-existing environment failures
    remain, 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, which
    is corroboration for the change and not evidence produced by it.
  • No backend or frontend runtime code changed, so no dotnet and no Vitest or Playwright run applies and
    none was performed.
  • That the six reds are exactly six distinct hosted failures. The run and job ids above are reproduced as
    recorded on the issues; two of them were confirmed directly against the API, the rest were not
    re-fetched.
  • The behaviour of the Windows leg after this change on a real hosted run, that is, that it still
    completes lint, typecheck, build, PWA worker and coverage green with the launcher step skipped.

Risk notes

  • CI-control change, risk class R4 under .claude/rules/ci-control.md and ADR-0066. Opened
    ready-for-review and parked for the maintainer under SC-10. I do not merge it.
  • The real risk is the lost coverage described above, not the mechanics. A PowerShell-only launcher
    regression is now invisible to CI until CI-04 #2328 registers the laptop runner. The new contract test
    and the TESTING_GUIDE paragraph exist so this is a recorded, reversible trade rather than silent drift.
  • Reverting is one line: delete the if: from the step. The contract test would then fail and name the
    reason, which is intended.
  • Frontend Unit (windows-latest) still runs and still reports, so no required context disappears and
    branch 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.
  • The new test file sits in scripts/ci/smart-ci/ rather than scripts/ci/ so the existing
    node --test scripts/ci/smart-ci/*.test.mjs glob in smart-ci-self-test.yml picks it up with no
    workflow edit. scripts/ci/*.test.mjs has no glob runner, so a file there would have been wired into
    nothing. The sibling workflow-contract test required-e2e-dependencies.test.mjs already lives in that
    directory.

Refs #2331

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.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Chris0Jeky

Copy link
Copy Markdown
Owner Author

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 (.github/workflows/**, T2): it stays parked for the maintainer's decision under OUTSTANDING_TASKS SC-10 and is not merged by an agent.

Confirmed: the workflow change is exactly two added lines (a comment and if: runner.os == 'Linux') on the launcher step; the matrix, job name, runs-on, both timeouts and the run line are byte-identical, so the required-context name does not change; the expression has an exact in-file precedent (the bundle-size step); nothing later in the job depends on the launcher step (its fixtures live under the OS temp directory); the placement contract test is wired through the existing scripts/ci/smart-ci/*.test.mjs glob in the Planner Self-Test lane with two workflow-contract siblings already in that directory, and it discriminates on removing the condition, renaming the step, dropping the Windows leg or adding an OS condition to lint/typecheck/build/coverage; the reusable workflow has exactly one caller (ci-required.yml), so no other job runs the suite on Windows; on Linux the PowerShell cases were already skipped, so the removal of hosted PowerShell launcher execution is real and is disclosed in the workflow comment and the guide.

Red-first evidence recorded on the PR: the placement test failed on the unmodified workflow (if was null), then passed; Smart CI suite 94/94; docs governance green. node --test scripts/ci/*.test.mjs is not green on this box before or after the PR (actionlint not installed; the local Bash launcher cohort), which is why the hosted Workflow Lint and Planner Self-Test runs at the exact head are the R4 proof.

Findings, all non-blocking, most of them decision points for the maintainer's SC-10 review rather than defects in the diff:

  1. MEDIUM, decision point: ci/policy.v1.json's launchers-windows group still maps scripts/dev-up.ps1 and dev-up.sh to the Windows frontend lane, which after this change executes no launcher code, and no hosted job in the repository runs dev-up.ps1 at all. The planner is shadow-only today, so it gates nothing. If this slice is accepted, CI-07's next slice should retarget that group (Linux lane plus a local Windows contract entry when the ownership manifest lands).
  2. MEDIUM, decision point: docs/ci/PRIVATE_REPO_CUTOVER_CHECKLIST.md section E and docs/ci/SMART_CI.md section 5 still describe the pre-SC-3 CI-07 target ("Windows leg narrowed to launcher/platform"), which is the inverse of what SC-3 now implies and this PR does. Both are older than the SC-3 re-ruling; reconciling them belongs with the maintainer's ruling on this slice rather than in a workflow PR.
  3. MEDIUM, fixed in f74f590: the guide named the local Windows command without saying its Bash: cases are known-red under Git Bash on a Windows box; the paragraph now names that cohort and says to read the result per case.
  4. LOW, recorded: ci-required.yml's header map still says "dev launcher ... (Ubuntu + Windows)"; left untouched to keep the diff to one workflow, to be corrected in the next CI-control slice.
  5. LOW, recorded: the retained #2378 comment justifies the 10-minute step timeout with a Windows measurement (6m31s); the Linux run of the same step is about 47 s, so the budget is generous but safe.
  6. LOW, fixed in f74f590: the guide's Last Updated line now carries this edit's date.
  7. LOW, accepted: the contract test pins the condition by exact string on purpose, so a later broadening fails loudly.

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 windows-latest wall clock per run); the replacement is the local Windows command until the CI-04 laptop runner is registered. The Linux case recorded as #2588 is not removed by this change.

Merge gate: maintainer review (SC-10) plus hosted Workflow Lint, Smart CI / Planner Self-Test and ci-required green at the final head.

@Chris0Jeky

Copy link
Copy Markdown
Owner Author

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.

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

Labels

None yet

Projects

Status: Pending

Development

Successfully merging this pull request may close these issues.

1 participant