PR #807 collapsed the top #code-agent-summary and per-message debug panels
into a 调试信息 dialog, but the conversation list still showed two hard-coded
System cards (界面模式 / Code Agent 状态) that fed availability into the
agent run path. Both appeared as full <article class="message-card
message-system"> bubbles before any user message on every session load,
contradicting the issue goal of a clean agent / user conversation feed.
- remove the ConversationPanel intro useMemo + [...intro, ...messages]
spread; the conversation list now only contains real agent / user
messages.
- move the static 界面模式 content to a small muted hint line under the
panel title (id=workspace-hint, .conversation-panel-hint).
- the live Code Agent availability snapshot is already covered by the
existing #code-agent-summary + 调试信息 dialog, so it is dropped.
- add a conversation-list empty-state placeholder so the panel keeps
height for layout smoke (messages.length === 0).
- delete the now-orphan MessageRuntimePath / MessageSessionContinuity /
MessagePendingContext components (no remaining callers per rg).
- extend tools/capture-issue-803-noise.mjs to report each .message-card
role plus systemMessageCount / roleCounts so layout-level evidence
can assert "no message-system in the conversation list".
web:check 12 pass / 0 fail; web:layout:build pass (desktop, narrow,
mobile). Issue: pikasTech/HWLAB#803
The Agent workspace (top #code-agent-summary and each agent message card)
exposed too many "未观测" / readiness / providerTrace / runtime-path rows
inline; per-message panels (MessageRuntimePath, MessageSessionContinuity,
MessagePendingContext) ate most of the card width and made the agent trace
events list (the only thing the user really wants to see) read at ~83% of
the card.
This change:
- introduces a reusable <DebugDialog> component (web/hwlab-cloud-web/src/components/shared/DebugDialog.tsx)
that surfaces the full availability / readiness / runnerTrace / raw JSON
payload only when the user clicks a 调试信息 button.
- shrinks codeAgentSummaryRows() in state/code-agent-status.ts to only
return rows with meaningful values; "未观测" / "字段缺失:证据不足" /
"DEGRADED:运行路径字段不完整" / "无"-only readiness blockers are
filtered out of the top summary and remain reachable via the dialog.
- rewrites MessageCard to drop the inline MessageRuntimePath /
MessageSessionContinuity / MessagePendingContext panels and to show a
single compact footer (timestamp + 调试信息 button). The pending running
hint is reduced to a one-line tag instead of a 7-row grid.
- makes .message-trace and .message-trace-events fill the message card so
the trace events list is the dominant element per the issue.
- adds tools/capture-issue-803-noise.mjs so CLI can log into the live or
local Cloud Web, capture the rendered #code-agent-summary / per-message
meta / trace widths into a JSON document, and diff before/after the
refactor.
web:check, web:layout, dev-cloud-workbench-smoke --static, and
dev-cloud-workbench-layout-smoke all pass on the local build.
Issue: pikasTech/HWLAB#803
Co-authored-by: HWLAB Agent <hwlab-agent@pikastech.local>
Follow-up to PR #798 (#795 final). PR #798 closed the total-timeout /
hard-cap issue, but left two residual code-path inconsistencies that
#802 captures:
- Submit path and refresh path used different trace-polling code:
submitMessage called `pollRunnerTrace` + `waitForAgentResult` (a
dual function pair from pre-#798), while hydrate() never subscribed
to the running trace at all. After a page refresh, the user saw
the cloud-api "running" state but no live trace events.
- The submit fail branch only dispatched a local "Code Agent 超时"
message; it never called `persistConversation`, so the failure was
invisible after F5 — the cloud-api conversation would show
"running" forever from the user's perspective.
This PR collapses both into a single `subscribeToTrace` entry point
and wires the refresh path into the same active subscription:
- `state/runner-trace.ts` — replace `waitForAgentResult` +
`pollRunnerTrace` with a single `subscribeToTrace(config)` that
handles both the result endpoint and the trace endpoint in one
`for(;;)` loop. Calls `onActivity` on EVERY successful poll (not
just on new events) so the per-poll inactivity window in
`fetchJson` does not fire on a healthy polling loop. Terminal
status -> `onComplete`; 5xx -> keep polling, no activity; 4xx ->
`onInfrastructureError`; `signal.aborted` -> silent return. The
hard-cap / 4x / `TRACE_HARD_CAP_ATTEMPTS` machinery is gone (was
already removed by #798).
- `state/trace-reattach.ts` — new `useTraceReattach` hook that
subscribes to the running trace on hydrate (same `subscribeToTrace`
call as submitMessage). Reuses an existing agent message slot for
the traceId if one exists; otherwise creates a placeholder. Persists
on both onComplete and onInfrastructureError. Path unification
achieved: one entry, two callers.
- `state/workbench.ts`:
- `submitMessage` calls `subscribeToTrace` directly with a
single-line `onActivity: () => updateActivity()` plus
`onComplete` / `onInfrastructureError` callbacks. The
`onInfrastructureError` branch now ALSO calls
`persistConversation`, persisting the fail state to cloud-api.
- The re-attach useEffect is replaced with a one-liner
`useTraceReattach({...})` call (workbench.ts stays under the
400-line guard).
- `scripts/fetchJson-inactivity.test.ts` — third case tightened:
200ms-cadence activity for 10s with `timeoutMs: 3000`; the
request must live the full 10s and abort only after activity
stops. Asserts `elapsed >= 10_000`.
- `docs/reference/spec-v02-hwlab-cloud-web.md` — the "Code Agent
Timeout Model" section is renamed "Code Agent Timeout Model 与
Path Unification" and now also pins: (a) `subscribeToTrace` is
the only entry; `waitForAgentResult` / `pollRunnerTrace` /
`TRACE_HARD_CAP_ATTEMPTS` MUST NOT exist; (b) `useTraceReattach`
MUST be wired in; (c) `persistConversation` is required in both
onComplete and onInfrastructureError; (d) `state.workspace.activeTraceId`
changes MUST re-attach. Includes a distilled history of
#775 / #777 / #791 / #795 / #797 / #798 / #802.
Verification
- `bun run scripts/tsc-check.ts` → strict React TSX, 0 explicit any
- `bun run check` → 5 pass / 0 fail (3 inactivity + 2 dist-contract)
- `bun run build` → 9 dist files verified fresh; `app.js`
238460 → 240990 B
- `state/trace-reattach.ts` is now wired in; `state/runner-trace.ts`
exports only `subscribeToTrace` (verified by tsc + grep)
- `workbench.ts` line count 400 (under the 400-line guard)
- New 200ms-cadence 10s test passes; old 100ms-cadence 2s test
and total-timeout 200ms test still pass.
Refs: HWLAB #802, #795, #777, #791, #798
Co-authored-by: Codex Agent <codex@hwlab.local>