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
tracking(desktop): move every test out of Electron E2E that does not need it
#4741 removed 22 layout-tier tests — transcript-scroll.spec.ts (774 lines), prompt-rail.spec.ts (622), one from streaming-remount.spec.ts — because they blocked main. This tracker puts that coverage back at the right tier and deletes the harness that made it fragile.
P0 is landed (#4766, dbf5afd735): 18 of the 22 rebuilt as Storybook play stories plus one new, 18 stories, no production code changed. Smoke 277 stories / 303 renders, 0.3–2.2s each against E2E originals that were all test.slow(). Follows #4727.
PR 2 is landed (#4786, 7f7843e1e5). Tier one is now 78 tests in 35 files.
Root cause
E2E holds a large majority of tests that never needed Electron — 110 tests, ~6 minutes, on the required check. #4523 bought 40% with four Xvfb workers and a warm, reused WebContents, which invalidated the premises those tests were written against: a fresh renderer per test, exclusive OS focus, unthrottled frames. Six flake reports in 43 hours followed.
#4707's trace shows the mechanism: the warm fixture's between-test readiness gate waitForSelector('[data-turn-id]') completes on the previous session's turn-fixture-1, and the assertion then observes turn-prompt-rail-111. Patching that gate treats a symptom — #4714 did exactly that and was closed unmerged. Shrinking tier one makes it unnecessary.
Target: 83 tests in 34 files → 4–8 that genuinely need Electron, plus a manual perf probe. Counts below are a first pass; each PR confirms its own before moving.
P1 remainder (20). ← next. workhub-reconstruction (3), skill-draft-lifecycle (2), goal-dialog-budget (1), new-task-draft-target (2), send-message (1), session-rail-render-contract (1), about-page (1), module-hub (1), parent-session-deletion (1), accessibility-coverage (7). The last is a judgement call: no geometry, but it traverses focus across the whole shell — decide whether that is a shell contract or a component one before moving.
P2 geometry cases, files stay (~17).session-workbar (18 geometry references), settings (10), workhub-layout (2), onboarding-viewport (its minimum-window case is genuinely Electron and stays).
Delete the harness.--workers and the four Xvfb displays in ci.yml; resetPromptRailWindow, promptRailWorker, the warm fixture (~87 lines) and the dead scrollMotion argument at fixtures.ts:419 in e2e/fixtures.ts; the releaseRendererObservations() preload bridge and sessions:e2e:release-renderer-observations channel; RuntimeHostSessionObservationRegistry.releaseTarget() (added by ci: cut single-job validation time by up to 40% #4523 for this alone — the registry itself is production infrastructure and stays); playwright.config.ts already back to workers: 1.
Rules the plan follows:
P1 needs extraction, P2 mostly does not. That is why 2 and 3 cannot be one PR and 4 and 5 could have been.
The E2E test is deleted in the same PR as the story or unit test that replaces it.
6 goes last on a measured cost. The e2e step is 5m03s at four workers; one worker is about +3.5 minutes on the required check until the count comes down. ci: cut single-job validation time by up to 40% #4523's 40% is not given back — what is saved is the ~68 tests that no longer start Electron at all.
6 triggers on the number, not on the checklist. 26 + 42 leaves 17, not 4–8. Re-count tier one after each batch.
Take fixture-thread-search off the warm fixture in the first PR that touches e2e/fixtures.ts. It is the only CI test still running on a reused window, so moving it retires the flaky(e2e): pinned tail can load earlier history after its settle check #4707 flake class early; the machinery itself stays until 6, because native-transcript-perf wants warm reuse by design.
Still uncovered
Three of the 22 are not in a story. Only one is a tier decision.
a gesture a nested scroller consumed does not release the tail
E2E — needs Chromium's own scroll chaining
—
The observer test landed in #4786 as a component test, where it can install its probe before the rail mounts; the rootMargin literal it matched is now a named constant. The remaining two are uncovered regressions today.
Check the props before planning an extraction.ChatView already took the transcript, the history seam, the growth signal and the rail's landmark index, so no fake backend was needed and the 120-prompt seeded session turned out to be unnecessary.
A dispatched wheel takes the production branch whenever the guard reads DOM state — composedPath(), computed overflowY. It does not when the behaviour is the browser's own.
smoke:storybook does not build. Run build-storybook first.
The smoke runs headless, which paints no platform scrollbar. Anything a scrollbar can occlude is inert on CI; SMOKE_HEADED=1 runs it headed.
The flake at this tier is waitFor boundaries, not the readings — a condition that goes true while layout is still resolving, with the real assertion read outside the retry. ~1% at 4x CPU throttle, never locally.
Scenario data lives in apps/desktop/src/main/e2e-fixture (1197 lines). Share it with the story side rather than writing a second copy; settled per PR.
What stays in Electron
proxy-password-editing — real HTTP server, the proxy-authorization header the main process actually sent, across two reloads
fixture-thread-search — a search hit's session key surviving the bridge intact
slash-command-compact — a Session-bearing shell's command list, and /compact reaching the Host rather than the model
onboarding-viewport — minimum window size
streaming-remount (4) — judgement: it injects failures through the bridge with rejectNextSessionObservation / rejectNextTranscriptOpen, genuinely cross-process even though the assertion is a React sequence
native-transcript-perf — CDP-driven, real compositor, manual probe behind MAKA_TRANSCRIPT_PERF
Non-goals
Not restoring the deleted specs to E2E. Not changing retries: 0. Not patching the readiness gate — PR 6 removes it. Not moving assertions that genuinely need Electron: native input, window-boundary drags, real folders, reload persistence, cross-process contracts.
Related
#4727 — this is the composition half of that discussion, without depending on a relevance selector's outcome. #4664 — out of scope; a product race, stays open as a product bug. #4714 — superseded, PR 6 deletes the gate it targets. #4259 — the reason P0's new story exists. #4582 — blocks the two session-switch tests above. #3944 — complementary: it widens which surfaces have stories, this puts assertions where they can run.
tracking(desktop): move every test out of Electron E2E that does not need it
#4741 removed 22 layout-tier tests —
transcript-scroll.spec.ts(774 lines),prompt-rail.spec.ts(622), one fromstreaming-remount.spec.ts— because they blockedmain. This tracker puts that coverage back at the right tier and deletes the harness that made it fragile.P0 is landed (#4766,
dbf5afd735): 18 of the 22 rebuilt as Storybookplaystories plus one new, 18 stories, no production code changed. Smoke 277 stories / 303 renders, 0.3–2.2s each against E2E originals that were alltest.slow(). Follows #4727.PR 2 is landed (#4786,
7f7843e1e5). Tier one is now 78 tests in 35 files.Root cause
E2E holds a large majority of tests that never needed Electron — 110 tests, ~6 minutes, on the required check. #4523 bought 40% with four Xvfb workers and a warm, reused WebContents, which invalidated the premises those tests were written against: a fresh renderer per test, exclusive OS focus, unthrottled frames. Six flake reports in 43 hours followed.
#4707's trace shows the mechanism: the warm fixture's between-test readiness gate
waitForSelector('[data-turn-id]')completes on the previous session'sturn-fixture-1, and the assertion then observesturn-prompt-rail-111. Patching that gate treats a symptom — #4714 did exactly that and was closed unmerged. Shrinking tier one makes it unnecessary.Target: 83 tests in 34 files → 4–8 that genuinely need Electron, plus a manual perf probe. Counts below are a first pass; each PR confirms its own before moving.
Plan — six PRs
P0. Transcript scrolling and prompt rail.Done, test(desktop): rebuild transcript and prompt rail coverage as stories #4766.Done, test(desktop): move the composer slash, paste and Skill-draft journeys off Electron #4786. Thirteen moved; two claims stayed in Electron asslash-command-menu(6) + composer trio (7).slash-command-compact.spec.ts— that a shell holding a Session offers the commands needing one, and that submitting/compactreaches the Host rather than the model. Both sit inline inapp-shell.tsxwith no seam under them, and opening one is what the architecture ratchet refuses.fixture-thread-searchmoved off the warm fixture here, retiring the flaky(e2e): pinned tail can load earlier history after its settle check #4707 flake class early as planned.workhub-reconstruction(3),skill-draft-lifecycle(2),goal-dialog-budget(1),new-task-draft-target(2),send-message(1),session-rail-render-contract(1),about-page(1),module-hub(1),parent-session-deletion(1),accessibility-coverage(7). The last is a judgement call: no geometry, but it traverses focus across the whole shell — decide whether that is a shell contract or a component one before moving.agent-graph-layout(1),link-color-contract(1),sidebar-geometry(1),transcript-measure(1),partial-history-notice(1),request-header-row-contract(1),settings-row-focus-ring(4),sidebar-titlebar-actions(2),sidebar-project-row(4),quote-selection(2),composer-plus-menu-stability(7). Mechanical — no extraction.session-workbar(18 geometry references),settings(10),workhub-layout(2),onboarding-viewport(its minimum-window case is genuinely Electron and stays).--workersand the four Xvfb displays inci.yml;resetPromptRailWindow,promptRailWorker, the warm fixture (~87 lines) and the deadscrollMotionargument atfixtures.ts:419ine2e/fixtures.ts; thereleaseRendererObservations()preload bridge andsessions:e2e:release-renderer-observationschannel;RuntimeHostSessionObservationRegistry.releaseTarget()(added by ci: cut single-job validation time by up to 40% #4523 for this alone — the registry itself is production infrastructure and stays);playwright.config.tsalready back toworkers: 1.Rules the plan follows:
fixture-thread-searchoff the warm fixture in the first PR that touchese2e/fixtures.ts. It is the only CI test still running on a reused window, so moving it retires the flaky(e2e): pinned tail can load earlier history after its settle check #4707 flake class early; the machinery itself stays until 6, becausenative-transcript-perfwants warm reuse by design.Still uncovered
Three of the 22 are not in a story. Only one is a tier decision.
The observer test landed in #4786 as a component test, where it can install its probe before the rail mounts; the
rootMarginliteral it matched is now a named constant. The remaining two are uncovered regressions today.Moving a test at this tier
From #4766:
ChatViewalready took the transcript, the history seam, the growth signal and the rail's landmark index, so no fake backend was needed and the 120-prompt seeded session turned out to be unnecessary.composedPath(), computedoverflowY. It does not when the behaviour is the browser's own.smoke:storybookdoes not build. Runbuild-storybookfirst.SMOKE_HEADED=1runs it headed.waitForboundaries, not the readings — a condition that goes true while layout is still resolving, with the real assertion read outside the retry. ~1% at 4x CPU throttle, never locally.Scenario data lives in
apps/desktop/src/main/e2e-fixture(1197 lines). Share it with the story side rather than writing a second copy; settled per PR.What stays in Electron
proxy-password-editing— real HTTP server, theproxy-authorizationheader the main process actually sent, across two reloadsfixture-thread-search— a search hit's session key surviving the bridge intactnew-task-reload— reload persistence; its send is fenced behind the fix(desktop): land prompt-rail jumps at the top and fence the e2e sends #4577 readiness barrierslash-command-compact— a Session-bearing shell's command list, and/compactreaching the Host rather than the modelonboarding-viewport— minimum window sizestreaming-remount(4) — judgement: it injects failures through the bridge withrejectNextSessionObservation/rejectNextTranscriptOpen, genuinely cross-process even though the assertion is a React sequencenative-transcript-perf— CDP-driven, real compositor, manual probe behindMAKA_TRANSCRIPT_PERFNon-goals
Not restoring the deleted specs to E2E. Not changing
retries: 0. Not patching the readiness gate — PR 6 removes it. Not moving assertions that genuinely need Electron: native input, window-boundary drags, real folders, reload persistence, cross-process contracts.Related
#4727 — this is the composition half of that discussion, without depending on a relevance selector's outcome. #4664 — out of scope; a product race, stays open as a product bug. #4714 — superseded, PR 6 deletes the gate it targets. #4259 — the reason P0's new story exists. #4582 — blocks the two session-switch tests above. #3944 — complementary: it widens which surfaces have stories, this puts assertions where they can run.