Three WorkHub tests failed intermittently on Linux CI while I was landing #5961, and one of them recurred on main right after the merge. #5961 caused none of them. The three PR runs used byte-identical trees, and that tree had already passed the full CI before the rebase. Each run failed a different test, and none of the failing tests renders the retention notices #5961 added. Each failure below has its own mechanism and fix, so they can be fixed and closed separately.
1. workhub-layout e2e still crashes Electron at the guarded closePopup after #5918
apps/desktop/e2e/workhub-layout.spec.ts › "WorkHub uses its coordination model and shared attachment composer" crashed the Electron main process again in the Desktop e2e step, after #5918 had closed #5917.
Seen on: #5961, run 37728038123 attempt 2 (head 8d05fd7b3). Attempt 3 of the same tree passed.
Error: jsHandle.evaluate: Target page, context or browser has been closed
> 150 | await mainWindow.evaluate((window) => {
at apps/desktop/e2e/workhub-layout.spec.ts:150:20
Mechanism. The process dies inside the single main-process task that #5918 introduced:
if (probe.workbarMenuOpen) probe.workbarMenu.closePopup(window);
The mainWindow.evaluate just before it (the container getVisible() check) succeeded, so the main process was alive when this task began. That leaves two possibilities, and CI logs cannot tell them apart:
Fix: stop opening a real native menu in this spec. Its assertions are about Maka state, not GTK: aria-expanded, the dock backdrop, and the native WorkHub view's visibility. Stub Menu.prototype.popup so it records the menu without calling the native implementation, then close by emitting menu-will-close. That removes closePopup from the test, and both crash paths with it. Product code never calls closePopup, so this is test-only.
2. WorkHub native browser smoke loses the CDP click sent right after Main closes
apps/desktop/scripts/workhub-browser-presentation-smoke.mjs (CI step "WorkHub native browser presentation smoke") fails at its last assertion:
AssertionError [ERR_ASSERTION]: background page must handle the native click after Main closes
'Test' !== 'Clicked'
at run (apps/desktop/scripts/workhub-browser-presentation-smoke.mjs:197:12)
Seen on:
main at f10a74d8e, run 37731524494 attempt 1. Every earlier phase passed: docked, menu-overlay, menu-dismissed, floating-conversation, panel-hidden, background-restored and redocked.
feature/chat-image-delivery, run 37588623379 (2026-10-07).
The smoke uses a synthetic fixture window and no AppShell renderer.
Mechanism (plausible; not reproduced locally). The test runs these steps back to back:
main.emit('close'), then main.destroy(). This reparents the live view into the floating window.
- A fixed
wait(100).
controller.navigate('…/page?main-closed').
- One
Input.dispatchMouseEvent press/release pair.
The page may not yet have produced a compositor frame or hit-test data in its new window under Xvfb, and Chromium drops input it cannot route. The smoke deliberately sends only one click, so a dropped event fails the run.
Fix: wait until the page can receive input before dispatching, rather than retrying the click. For example:
- await
document.visibilityState === 'visible' and two requestAnimationFrame callbacks via executeJavaScript; or
- force a frame with
webContents.capturePage().
Keep the single click, so a genuinely lost event still fails.
3. Storybook product-workhub--retry-while-work-filtered intermittently never shows the work filter
The Storybook smoke failed this story both under 4-way concurrency and when retried alone:
[product-workhub--retry-while-work-filtered (light/default)] console.error:
TestingLibraryElementError: Unable to find role="button" and name "显示全部对话"
Seen on: #5961, run 37728038123 attempt 1. The same tree passed the Storybook smoke on attempts 2 and 3. The story renders WorkHubRoot only.
Where it fails. In RetryWhileWorkFiltered.play (apps/desktop/stories/workhub.stories.tsx), the steps are:
- Send
FILTERED_RETRY_PROBE.
- Wait for the
Temporary Host failure alert.
- Click the first
.workhub-message-rail.
waitFor(() => getByRole('button', { name: '显示全部对话' })), with the default 1 s timeout. This step times out.
Ruled out locally. I built Storybook at f10a74d8e and drove the story through the CI smoke's own smokeStory(). It passed 34/34 runs: 10 without throttling, 12 at 2× and 12 at 3× CDP CPU throttling. At 6× the story cannot finish in 15 s at all, which is a different failure. Instrumentation showed the click always landed on a connected rail with aria-pressed="false" and pointer-events: auto. That rules out a click on a detached node, and a click swallowed by the 1.2 s WorkHub reveal gate.
Open question. On the CI runner, either the filtered re-render takes longer than the 1 s waitFor, or something clears the selection after it was set. onSubmit clears it only at send time, before the failure. A CI trace or screenshot at the failure point would settle which.
Next step:
- Have the smoke capture a screenshot or trace on play-function errors.
- Check whether this story, unlike
SendWhileWorkFiltered, should wait for the composer to settle after the failed send before clicking the rail.
Refs #5917, #5918, #5961.
Three WorkHub tests failed intermittently on Linux CI while I was landing #5961, and one of them recurred on
mainright after the merge. #5961 caused none of them. The three PR runs used byte-identical trees, and that tree had already passed the full CI before the rebase. Each run failed a different test, and none of the failing tests renders the retention notices #5961 added. Each failure below has its own mechanism and fix, so they can be fixed and closed separately.1.
workhub-layoute2e still crashes Electron at the guardedclosePopupafter #5918apps/desktop/e2e/workhub-layout.spec.ts› "WorkHub uses its coordination model and shared attachment composer" crashed the Electron main process again in theDesktop e2estep, after #5918 had closed #5917.Seen on: #5961, run 37728038123 attempt 2 (head
8d05fd7b3). Attempt 3 of the same tree passed.Mechanism. The process dies inside the single main-process task that #5918 introduced:
The
mainWindow.evaluatejust before it (the containergetVisible()check) succeeded, so the main process was alive when this task began. That leaves two possibilities, and CI logs cannot tell them apart:menu-will-closehas not reached JS yet, so the flag is stale. This is the test(desktop): workhub-layout e2e crashes Electron when the native menu auto-dismisses before closePopup #5917 race, narrowed but not closed.closePopup(window)can crash on Linux even for a live popup in this window setup.Fix: stop opening a real native menu in this spec. Its assertions are about Maka state, not GTK:
aria-expanded, the dock backdrop, and the native WorkHub view's visibility. StubMenu.prototype.popupso it records the menu without calling the native implementation, then close by emittingmenu-will-close. That removesclosePopupfrom the test, and both crash paths with it. Product code never callsclosePopup, so this is test-only.2. WorkHub native browser smoke loses the CDP click sent right after Main closes
apps/desktop/scripts/workhub-browser-presentation-smoke.mjs(CI step "WorkHub native browser presentation smoke") fails at its last assertion:Seen on:
mainatf10a74d8e, run 37731524494 attempt 1. Every earlier phase passed: docked, menu-overlay, menu-dismissed, floating-conversation, panel-hidden, background-restored and redocked.feature/chat-image-delivery, run 37588623379 (2026-10-07).The smoke uses a synthetic fixture window and no AppShell renderer.
Mechanism (plausible; not reproduced locally). The test runs these steps back to back:
main.emit('close'), thenmain.destroy(). This reparents the live view into the floating window.wait(100).controller.navigate('…/page?main-closed').Input.dispatchMouseEventpress/release pair.The page may not yet have produced a compositor frame or hit-test data in its new window under Xvfb, and Chromium drops input it cannot route. The smoke deliberately sends only one click, so a dropped event fails the run.
Fix: wait until the page can receive input before dispatching, rather than retrying the click. For example:
document.visibilityState === 'visible'and tworequestAnimationFramecallbacks viaexecuteJavaScript; orwebContents.capturePage().Keep the single click, so a genuinely lost event still fails.
3. Storybook
product-workhub--retry-while-work-filteredintermittently never shows the work filterThe Storybook smoke failed this story both under 4-way concurrency and when retried alone:
Seen on: #5961, run 37728038123 attempt 1. The same tree passed the Storybook smoke on attempts 2 and 3. The story renders
WorkHubRootonly.Where it fails. In
RetryWhileWorkFiltered.play(apps/desktop/stories/workhub.stories.tsx), the steps are:FILTERED_RETRY_PROBE.Temporary Host failurealert..workhub-message-rail.waitFor(() => getByRole('button', { name: '显示全部对话' })), with the default 1 s timeout. This step times out.Ruled out locally. I built Storybook at
f10a74d8eand drove the story through the CI smoke's ownsmokeStory(). It passed 34/34 runs: 10 without throttling, 12 at 2× and 12 at 3× CDP CPU throttling. At 6× the story cannot finish in 15 s at all, which is a different failure. Instrumentation showed the click always landed on a connected rail witharia-pressed="false"andpointer-events: auto. That rules out a click on a detached node, and a click swallowed by the 1.2 s WorkHub reveal gate.Open question. On the CI runner, either the filtered re-render takes longer than the 1 s
waitFor, or something clears the selection after it was set.onSubmitclears it only at send time, before the failure. A CI trace or screenshot at the failure point would settle which.Next step:
SendWhileWorkFiltered, should wait for the composer to settle after the failed send before clicking the rail.Refs #5917, #5918, #5961.