What happened
The Desktop E2E test below fails intermittently under concurrent CI load:
apps/desktop/e2e/transcript-scroll.spec.ts
history asked for at the very top of the scroller still lands above the reader
The assertion waiting for the first resident turn to change times out after 20 seconds. In the observed CI failure, the first resident turn remained turn-prompt-rail-111.
Expected behavior: the test should deterministically wait for the transcript's initial tail positioning to finish, scroll to the top, request earlier history, and verify that the loaded history lands above the reader.
Observed behavior: the test can execute root.scrollTop = 0 while the scroller is already at 0. That assignment is a no-op, so Chromium emits no reader scroll event and requestEarlier / loadEarlier is never triggered.
This appears to be a test-readiness race rather than a product behavior defect.
How to reproduce
From apps/desktop:
-
Build the Desktop app and workspace dependencies.
-
Run the affected test repeatedly with four Playwright workers:
npm run build:with-deps
npx playwright test \
--config e2e/playwright.config.ts \
e2e/transcript-scroll.spec.ts \
--grep "history asked for at the very top" \
--repeat-each=12 \
--workers=4
-
Observe that some iterations time out while waiting for the first resident turn to change.
Reproduction results during investigation:
- Single worker, five isolated runs: 5/5 passed.
- Four workers, 12 repeated runs: 2 failures.
- Four workers, 16 repeated runs with temporary read-only diagnostics: 1 failure.
The failing diagnostic sample, captured before the test assigned root.scrollTop = 0, was:
{
"scrollTop": 0,
"scrollHeight": 3246,
"clientHeight": 780
}
Because the assignment is 0 -> 0, it does not emit the scroll event used by useChatScroll to request earlier history. The transcript scroll authority completes its initial tail pin only afterward.
Environment
Logs, screenshots, or additional context
Related PR: #4417
The failed CI job completed with:
- 104 passed
- 4 skipped
- 1 failed
Lint, build, typecheck, and the observer E2E tests added by PR #4417 all passed.
Root cause
The promptRailWindow setup waits for the transcript DOM to appear, but the affected test does not wait for initial tail positioning to settle. Under concurrent/Xvfb load, the test can reach its top-of-scroller action before the initial tail pin.
Suggested fix
Before assigning root.scrollTop = 0, deterministically wait for a single scroll-metrics sample satisfying both:
scrollTop > 0
scrollHeight - scrollTop - clientHeight <= 4
Then perform the existing scroll-to-top action and history-load assertions.
A fixed delay or a larger 20-second assertion timeout would only mask the readiness race.
Validate the fix with:
- The affected test using
--repeat-each and --workers=4.
- The complete
transcript-scroll.spec.ts E2E file.
What happened
The Desktop E2E test below fails intermittently under concurrent CI load:
apps/desktop/e2e/transcript-scroll.spec.tsThe assertion waiting for the first resident turn to change times out after 20 seconds. In the observed CI failure, the first resident turn remained
turn-prompt-rail-111.Expected behavior: the test should deterministically wait for the transcript's initial tail positioning to finish, scroll to the top, request earlier history, and verify that the loaded history lands above the reader.
Observed behavior: the test can execute
root.scrollTop = 0while the scroller is already at0. That assignment is a no-op, so Chromium emits no reader scroll event andrequestEarlier/loadEarlieris never triggered.This appears to be a test-readiness race rather than a product behavior defect.
How to reproduce
From
apps/desktop:Build the Desktop app and workspace dependencies.
Run the affected test repeatedly with four Playwright workers:
Observe that some iterations time out while waiting for the first resident turn to change.
Reproduction results during investigation:
The failing diagnostic sample, captured before the test assigned
root.scrollTop = 0, was:{ "scrollTop": 0, "scrollHeight": 3246, "clientHeight": 780 }Because the assignment is
0 -> 0, it does not emit the scroll event used byuseChatScrollto request earlier history. The transcript scroll authority completes its initial tail pin only afterward.Environment
Logs, screenshots, or additional context
Related PR: #4417
The failed CI job completed with:
Lint, build, typecheck, and the observer E2E tests added by PR #4417 all passed.
Root cause
The
promptRailWindowsetup waits for the transcript DOM to appear, but the affected test does not wait for initial tail positioning to settle. Under concurrent/Xvfb load, the test can reach its top-of-scroller action before the initial tail pin.Suggested fix
Before assigning
root.scrollTop = 0, deterministically wait for a single scroll-metrics sample satisfying both:scrollTop > 0scrollHeight - scrollTop - clientHeight <= 4Then perform the existing scroll-to-top action and history-load assertions.
A fixed delay or a larger 20-second assertion timeout would only mask the readiness race.
Validate the fix with:
--repeat-eachand--workers=4.transcript-scroll.spec.tsE2E file.