Skip to content

fix(ci): deterministic wait at live-gui.spec.ts:35 (W9-2a flake fix) - #197

Merged
Ghenghis merged 1 commit into
feat/hermes3d-7-complete-gui-repo-wiringfrom
claude/w9-2a-base-flake-fix
May 10, 2026
Merged

Ghenghis merged 1 commit into
feat/hermes3d-7-complete-gui-repo-wiringfrom
claude/w9-2a-base-flake-fix

Conversation

@Ghenghis

Copy link
Copy Markdown
Owner

Summary

Deterministic fix for the base-branch CI flake at live-gui.spec.ts:35 (and the same root-cause failure mode in agents.spec.ts:20 and any other spec calling assertNoErrors).

Root cause

start-e2e-stack.mjs spawned uvicorn (API on :8765, optional desktop-compat on :8642) and Vite (:5173) concurrently. Playwright's webServer.url probes only the single Vite URL — when Vite's listener finished binding before uvicorn, Playwright considered the stack ready, the test page loaded, and the React app's initial fetch fan-out hit net::ERR_CONNECTION_REFUSED. Those errors landed in the pageerror / console capture installed by attachErrorCapture() and tripped assertNoErrors() (_helpers.ts:116).

Confirmed in CI failure log of run 25619531513: dozens of + "Failed to load resource: net::ERR_CONNECTION_REFUSED" entries before the expect(errors).toEqual([]) assertion.

Fix

start-e2e-stack.mjs now spawns API servers FIRST, awaits each /health (60s deadline, 250ms backoff), then spawns Vite. When Playwright's :5173 probe succeeds the API listener is already bound and serving — so the page's first fetch wave never sees ERR_CONNECTION_REFUSED.

  • Deterministic (gated on real readiness, not a wall-clock timeout)
  • No waitForTimeout flake-mask
  • No test-side changes; one starter file, +22 net LoC
  • Backward-compatible: desktop-compat gate is conditional on desktopPort being set, mirroring the existing branching

Evidence

Local 5x re-run of live-gui.spec.ts:35 (CI=1, no reuseExistingServer):

=== Run 1 ===  1 passed (23.6s)
=== Run 2 ===  1 passed (6.7s)
=== Run 3 ===  1 passed (6.8s)
=== Run 4 ===  1 passed (6.6s)
=== Run 5 ===  1 passed (6.7s)

Plus agents.spec.ts (which the CI log showed actually failing under the same root cause): 1 passed (19.3s).

Unblocks

Per 03_implementation/docs/handoffs/W9-2_GUI_STABILIZATION_LOG_2026-05-09.md lines 113-118, all 5 of these PRs are blocked on this same base-branch flake. They should rebase onto this fix once merged.

Sources

  • Playwright webServer docs — webServer.url polls a single URL; multi-process stacks need their own readiness gate inside the starter
  • Playwright Best Practices — avoid waitForTimeout; wait on explicit conditions

Test plan

Hermes evidence chain: PASS
Task ID: W9-2A-BASE-FLAKE-FIX-2026-05-10
hermes_run_gate: e2e-flake-fix

Co-authored-by: Claude Opus 4.7 (1M context) noreply@anthropic.com

…ED race (W9-2a)

start-e2e-stack.mjs spawned uvicorn (port 8765 + 8642) and Vite (5173)
concurrently. Playwright's webServer.url probe targets only :5173, so
when Vite finished binding before uvicorn, the page-load fetch fan-out
hit ERR_CONNECTION_REFUSED. Those errors accumulated in
attachErrorCapture() and tripped assertNoErrors(), causing the
"live-gui.spec.ts:35" flake (and the same root cause in
agents.spec.ts:20 — see W9-2_GUI_STABILIZATION_LOG).

Fix: spawn API servers first, await /health 200 (60s deadline,
250ms backoff), then spawn Vite. When Playwright's :5173 probe
succeeds the API listener is already bound. Deterministic, no
test-side timeouts, no skips.

Re-run on this branch: live-gui.spec.ts:35 = 5/5 PASS;
agents.spec.ts = 1/1 PASS (was failing on same race).

Unblocks: #181, #189, #190, #191, #192 (5 GUI PRs blocked on this
base flake per W9-2 lane handoff).

Sources:
- https://playwright.dev/docs/api/class-testconfig#test-config-web-server
  (webServer.url polls a single URL — multi-process stacks need their
  own readiness gate)
- https://playwright.dev/docs/best-practices#testing-philosophy
  (avoid waitForTimeout; wait for explicit conditions)

Files
  03_implementation/ui/scripts/start-e2e-stack.mjs (+22 net LoC)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6ae0d352-7d43-454d-ba92-773a7bdd2295

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/w9-2a-base-flake-fix

Comment @coderabbitai help to get the list of available commands and usage tips.

@Ghenghis
Ghenghis merged commit 2c55c9f into feat/hermes3d-7-complete-gui-repo-wiring May 10, 2026
3 checks passed
@Ghenghis
Ghenghis deleted the claude/w9-2a-base-flake-fix branch May 10, 2026 06:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant