Repository navigation
[Bug]: the required dashboard-browser lane is red on main — a steward view switch drops the live turn's elapsed receipt #7384
Description
Preflight
- I searched existing issues and discussions for this behavior.
- This report is not an unpatched security vulnerability.
- The report and attachments contain no credentials or private/internal material.
Issue origin
Reproduced in a real environment (native Windows source checkout) and confirmed against the hosted required lane.
LoopX version or commit
93bb1ed2794685aec8325142d4b9a31860e93428 (current main, LoopX 2.1.0). Regression range starts at 6275d180366bcd0963073d7e6b0b7005b0b6d79e (merge of #7320, 7a48d6709).
Host or runtime surface
Dashboard personal workspace (browser acceptance). Not host-specific; reproduced on native Windows 11 / CPython 3.14.3 / Node 26.11.1 with the Playwright Chromium headless shell, and observed on the hosted Ubuntu runner.
LoopX area
Presentation (dashboard personal workspace chat / overview receipt).
Problem
The required dashboard-browser job of Python Tests is deterministically red on main, so dashboard-acceptance fails, checks fails and merge-gate fails for every pull request that triggers the frontend qualification. The failing acceptance scenario is conversation-activity, whose stated guarantee is "view switch keeps request elapsed time".
Two separate facts combine:
- Switching the steward view to 总览 changes the React parent of
PersonalGoalHome:dashboard-page.tsxrendershomedirectly, or insideAppStewardEntrywhendefaultStewardEntryis true (the entry is selected bysearch.view === "conversation"with no binding; introduced by feat(chat): open the selected original steward from App Conversation #7320,7a48d6709). Flipping the view therefore remountsPersonalGoalHomeand drops the live message state. - On remount the history recovery path (
dashboard-page.tsx,appendManagerAssistantMessagecall around lines 1842-1855) re-creates the pending assistant receipt and derivesstartedAtonly fromactiveSnapshot?.active_turn?.created_at. The browser fixture's session snapshot returnsactive_turnwithoutcreated_at(examples/personal-workspace-browser/fixture.mjs:1849), while the production snapshot returns the stored turn record, which carriescreated_at(loopx/chat_store.py:1976-1994). With no start time,MessageActivityrenders no.personal-message-elapsed(message-activity.tsx:27-30,45), so the overview tray never shows the live turn's elapsed time.
The current failure is therefore a state-loss regression from the App chat entry, not a slow-runner flake: the same scenario passes before #7320 and fails at every commit since.
Who is harmed and how much. Every pull request whose change plan includes frontend qualification inherits a failing required check; the merged #7377 shows dashboard-browser (1) and (2), checks, pytest and merge-gate failing while the PR was merged with admin bypass, so the normal merge path is blocked. The maintainer must manually override the gate for each merge instead of reading it as a signal. For users, switching from the steward chat to the overview during an in-flight turn re-creates the receipt, loses the elapsed/quiet feedback and makes the two views disagree about the same request.
Minimal reproduction
From a source checkout of 93bb1ed27:
npm ci --ignore-scripts
npm ci --ignore-scripts --prefix apps/presentation/dashboard
(cd apps/presentation/dashboard && npx playwright install chromium --only-shell)
LOOPX_PERSONAL_WORKSPACE_SCENARIO=conversation-activity \
LOOPX_PLAYWRIGHT_PACKAGE="$PWD/apps/presentation/dashboard/node_modules/playwright" \
node examples/personal-workspace-browser-smoke.mjsObserved at 93bb1ed27: 3/3 runs fail after about 33 s.
scenario-start=conversation-activity
scenario-end=conversation-activity duration_ms=32974
locator.textContent: Timeout 30000ms exceeded.
Call log:
- waiting for locator('.personal-manager-conversation-tray').locator('.personal-message-elapsed')
at Object.run (.../examples/personal-workspace-browser/conversation-activity.mjs:55:68)
Debug state of the same message in the two views (instrumented locally, reverted):
chat view: {id: "2", pending: "true", started: "1793009124521", elapsed: "已用时 25秒"}
overview: {id: "2", pending: "true", started: "undefined", elapsed: null}
The tray message is created by the recovery path: forcing that path's startedAt to a sentinel made the tray render the sentinel.
Before/after range (same command, same host):
06f51b7e4 (parent of the #7320 merge): ok, duration_ms=14337
6275d1803 (#7320 merge): fails at conversation-activity.mjs:43 waiting for the composer
93bb1ed27 (current main): fails at conversation-activity.mjs:55 waiting for the tray elapsed element
Hosted evidence:
- Merged PR fix(chat): preserve latest reply through layout changes #7377, run
40297894327, job121489050276(dashboard-browser (1)):locator.textContent: Timeout 30000ms exceeded, same.personal-manager-conversation-tray .personal-message-elapsedlocator,2026-10-26T09:22:06Z;checksjob121493030420thenmerge-gatejob121493324707fail. - PR fix(leases): treat case aliases as overlapping write scopes #7252:
dashboard-browser (1)and(2),checksandmerge-gatefail as well.
Expected behavior
- The required
dashboard-browserjob is green onmainfor an unchanged checkout. - Switching from the steward chat to the overview keeps the same pending receipt and its elapsed/quiet reading, as the scenario asserts: the elapsed text in the overview tray equals the chat view's.
Actual behavior
- The required lane fails deterministically, and
checks/merge-gatefail with it. - The overview re-creates the pending receipt without a start time, so
.personal-message-elapsednever appears and the tray shows no elapsed reading.
Sanitized diagnostics
$ LOOPX_PERSONAL_WORKSPACE_SCENARIO=conversation-activity \
LOOPX_PLAYWRIGHT_PACKAGE=<dashboard>/node_modules/playwright \
node examples/personal-workspace-browser-smoke.mjs
scenario-end=conversation-activity duration_ms=32974
locator.textContent: Timeout 30000ms exceeded.
- waiting for locator('.personal-manager-conversation-tray').locator('.personal-message-elapsed')
at Object.run (<repo>/examples/personal-workspace-browser/conversation-activity.mjs:55:68)
# same scenario at the parent of the #7320 merge
$ git checkout 06f51b7e4 && node examples/personal-workspace-browser-smoke.mjs
personal-workspace-browser-smoke (development): ok
scenarios=conversation-activity
Additional context
- The adjacent required lane is already reported separately: [Bug]: the required chat-bundle-browser lane is red on main — the read-only source badge repeats the visible Goal title #7378 / fix(workspace): stop the read-only source badge from repeating the Goal title #7380 (
chat-bundle-browser). This issue is thedashboard-browserlane; the two jobs fail for different reasons and either one alone keepschecksred. - fix(chat): retain one observer for active managed turns #7354 (
fcfe57fb9) extended live-observer retention, but only forboundandmanagedcontexts; the steward/manager context still re-creates the receipt on remount. - Two candidate repairs need an owner decision because both change user-visible entry/chat behavior: (a) keep the steward home mounted across the entry/view switch instead of changing its parent element, or (b) make the live and recovered receipts share one canonical start (for example the server turn's
created_at) and update the fixture to model the productionactive_turnshape. Option (a) touches the App chat entry's first screen; option (b) changes which timestamp defines elapsed time. I did not implement either in this report.
AI disclosure: this report was prepared with AI assistance at the account owner's direction. The reproduction commands, local runs and before/after checks above were executed in this environment; the owner set the contribution constraints and will review any follow-up change.
Activity
coordination: record agent-n4v7 no-PR outcome and issue loopx-project…
JasonBuildAI commentedon Oct 26, 2026
Second required shard, same regression range, reproduced locally.
dashboard-browser (2)fails incomposer-session-admission(examples/personal-workspace-browser/composer-session-admission.mjs:136):Hosted evidence: run
40297894327, job121489050029,2026-10-26T09:17:36Z(aftercomposer-session-admissionended at 8176 ms). Local, single scenario:The scenario message is only the diagnostic. The composer is disabled because the new App chat entry sets
workspaceConversations.entryGate(dashboard-page.tsx:2972, fromappEntryBlocked), andcomposerBlockedincludes it (personal-workspace-page.tsx:1380). The scenario navigates to the manager conversation after an unconfirmed Goal instruction and expects Send to be enabled; after #7320 that path goes through the steward entry gate, so the composer is disabled before any pending-state question is reached.So both required
dashboard-browsershards fail from the #7320 App chat entry change:PersonalGoalHomeand the overview re-creates the receipt without a start time;Either failure alone keeps
checks(and thereforemerge-gate) red. A test-only patch for shard 2 would hide the shard 1 state loss rather than repair it, and changing the entry gate or its acceptance flow is the owner's call, which is why this report does not include a code change.