fix(tui): show busy startup loader during post-connect initialization [AI-assisted]#93999
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 6, 2026, 12:15 AM ET / 04:15 UTC. Summary PR surface: Source +12, Tests +24. Total +36 across 3 files. Reproducibility: yes. by source inspection: current main and v2026.6.11 set Review metrics: none identified. Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Next step before merge
Security Review detailsBest possible solution: Land the narrow TUI startup-loader fix after exact-head checks pass, then let #74385 close through the merged PR. Do we have a high-confidence way to reproduce the issue? Yes, by source inspection: current main and v2026.6.11 set Is this the best way to solve the issue? Yes. Reusing the existing busy-loader path and clearing only the exact startup-owned state is the narrow maintainable fix; it avoids widening AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 37f96bde4d90. Label changesLabel justifications:
Evidence reviewedPR surface: Source +12, Tests +24. Total +36 across 3 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (3 earlier review cycles) |
|
Addressed the correctness concern from the last review: the post-connect Changes:
Verified: @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Addressed the remaining review finding (
Verified: On the real-interactive-proof ask: the TUI requires an interactive TTY and won't boot headless on Windows ( @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Added real-render PTY evidence to the PR body (addressing the "helper terminal output" gap): Captured the ACTUAL rendered terminal bytes from the production AFTER (PR head 0a5b6eb) — real rendered status line: BEFORE (upstream main) — real rendered status line, same harness: So on main the loader never renders during init (0 "starting up" frames); on the PR head the busy "starting up" loader renders during post-connect init then clears to the unchanged "local ready | idle" ready line. The reconnect-owned-streaming preservation half is covered by the real exported Honest scope: the render path driven is production code under a real PTY, but the harness backend is a test fixture (not a live gateway/embedded runtime), and a slow-init fixture makes the loader window visible. A real-backend interactive Terminal Hatch recording on physical hardware is still outstanding — a maintainer can capture it via @clawsweeper re-review |
|
Strengthened the proof with a REAL embedded-backend local runtime capture (not the fake-backend harness): Ran So the real local runtime/session path is exercised end-to-end (this is not the fake-backend harness barred by and on upstream main the same harness renders 0 "starting up" frames (no loader — the reported freeze). The remaining gap is a real interactive Terminal Hatch run with naturally slow first-run init on physical hardware, which the contributor cannot capture (Windows host cannot boot the TUI headless). That can be captured via @clawsweeper re-review |
|
@steipete @vincentkoc — requesting a maintainer Mantis capture for the one piece of proof I could not produce as an external contributor. What the fix does (bot-endorsed): adds a The proof I could and couldn't capture (all on Linux, real Captured (in the PR body):
Could NOT capture (the gap):
So the one missing artifact is a real interactive Terminal Hatch run with naturally slow first-run init showing the ClawSweeper itself flags this as the sole remaining rank-up move and suggests exactly this capture. Could a maintainer run it? CI is fully green (65/65) on |
0a5b6eb to
bd74897
Compare
|
Maintainer refresh complete at What changed:
Verification:
Remote proof: Blacksmith Testbox through Crabbox, Thanks @ml12580 for the original diagnosis and fix direction. Exact-head land-ready update: 5ec2bb1 is the clean current-main-plus-reviewed-patch head. Hosted CI run https://github.com/openclaw/openclaw/actions/runs/28767169467 passed at that exact SHA. The rebase changed ancestry only; the tested diff and Testbox/browser/PTY proof above are unchanged. Known proof gaps: none. |
8f1d8d8 to
5ec2bb1
Compare
|
Merged via squash.
|
Summary
client.onConnectedinsrc/tui/tui.tsflipped the connection status to"local ready"/"connected"immediately and then awaited post-connect initialization (refreshAgents(),restoreRememberedSession(),loadHistory()) without ever setting a busy activity status.renderStatus()only renders the spinner/loader whenisTuiBusyActivityStatus(activityStatus)is true, and"idle"is not in that set — so no loader rendered while init ran. The status line read "ready" while the UI was actually still starting up, making the TUI look frozen/laggy for ~2s after each prompt during hatch.bug,regression, P2) reported against Terminal Hatch. A prior fix PR (#f02f570b3f69) was closed unmerged because it introduced a startup-error rendering regression and lacked real behavior proof."startup failed"text (the prior PR's regression is avoided).onConnectedrestructure insrc/tui/tui.ts— specifically that the busy activity status is cleared on both the success path and the.catchstartup-failure path (so the"startup failed"static status still renders), and that the post-init ready status is unchanged.Linked context
Closes #74385
Related: prior closed fix attempt f02f570 (closed unmerged — startup-error regression + missing real behavior proof).
Was this requested by a maintainer or owner? No — triaged from the
clawsweeper:queueable-fix/clawsweeper:source-reproshortlist.Real behavior proof (required for external PRs)
runTui()/renderStatus()/Loader render path under a real PTY (src/tui/tui-pty-harness.e2e.test.ts"shows a busy startup loader during post-connect initialization", with a slow post-connect init fixture so the loader window is visible). Also Windows 10 LTSC, Node v22.17.1 for the exported-helper reconnect-preservation check.OPENCLAW_TUI_PTY_MIRROR_PATHset to capture the actual rendered terminal bytes from the productionrunTui/onConnected/renderStatuspath, on PR head (AFTER) and on main (BEFORE). (2) Rannode --import tsx .tmp/startup-proof.mjsimporting the REAL exported helpers (isTuiBusyActivityStatus,isTuiActiveRunActivityStatus,resolveStartupActivityStatus) to show the reconnect-preservation decision.reconnectStreamingWatchdog()has already restoredstreamingfor a still-active run,resolveStartupActivityStatusnow PRESERVES that status instead of overwriting it withstarting up, and the post-init idle clear is gated so an in-flight run adopted byloadHistory()(which setsstreaming) keeps streaming — reconnect no longer hides active work behind the startup loader.runTui/renderStatus/Loader render path under a real PTY with a slow-init fixture showing the "starting up" loader paint (fake-backend harness — persrc/tui/AGENTS.mdthis must not be claimed as proof of the embedded runtime itself); (2) a REAL embedded-backend local run (tui-pty-local.e2e.test.ts, only the model HTTP endpoint mocked) proving the real local runtime boots,onConnectedpost-connect init completes, the status reaches "local ready | idle", and a full chat round-trip works. In that real run the post-connect init was too fast on a fresh workspace for the "starting up" loader to visibly paint (the loader window is only visible when init is slow, which is the exact scenario issue [Bug]: Stuck and ultra slow during Hatch (terminal mode) - took a minute to come back up #74385 reports on heavy first-run Hatch onboarding). A real interactive Terminal Hatch onboarding run against a live backend on physical hardware with naturally slow init was not captured by the contributor (the TUI needs an interactive TTY and the contributor's Windows host cannot boot it headless). That real-backend interactive recording with slow init is still outstanding; per the ClawSweeper review a maintainer can capture it via:@openclaw-mantis visual task: capture OpenClaw TUI during slow post-connect initialization and verify the starting up loader appears without hiding active streaming after reconnect.Tests and validation
Commands run locally (Windows, Node v22.17.1):
pnpm tsgo— passed (TypeScript strict, no errors).pnpm lint— passed (oxlint, full shard run).pnpm format:check— the three changed files are clean (the 55 unrelated format failures pre-exist on main and are an environment artifact of Node 22.17 vs the required 22.19; not introduced here).pnpm exec vitest run src/tui/tui.test.ts -t "isTuiBusyActivityStatus"— the new unit assertion fails before the fix (expected false to be true) and passes after.pnpm exec vitest run src/tui/tui-command-handlers.test.ts src/tui/tui-event-handlers.test.ts src/tui/tui-session-actions.test.ts— 171 passed, no regressions.pnpm build— core compilation (tsdown) succeeded; the post-buildwrite-cli-startup-metadatastep fails only because this machine runs Node 22.17.1 (< required 22.19.0) — unrelated to this change; CI runs Node 22.19+.pnpm check:host-env-policy:swift— skipped on Windows (no Swift toolchain).Regression coverage added:
src/tui/tui.test.ts— unit assertionisTuiBusyActivityStatus("starting up") === true(deterministic, fails before / passes after).src/tui/tui-pty-harness.e2e.test.ts— PTY behavioral test that drives the realrunTui/onConnectedpath with a slow post-connect init and asserts the busy"starting up"loader renders before"local ready"(runs in the Linux PTY CI shard; not reliably bootable under tsx+PTY on Windows).What failed before this fix:
isTuiBusyActivityStatus("starting up")returnedfalse, sorenderStatus()took the static-text branch and no loader rendered during onConnected init.Risk checklist
Did user-visible behavior change? Yes — intentionally. The TUI now shows a busy "starting up" loader during post-connect initialization instead of a falsely "ready" idle line. The final ready state is unchanged.
Did config, environment, or migration behavior change? No.
Did security, auth, secrets, network, or tool execution behavior change? No. No CODEOWNERS secops paths touched.
What is the highest-risk area? The
client.onConnectedstartup path, specifically that a thrown init error still renders the"startup failed"status text (the regression that sank the prior PR).How is that risk mitigated? The success path clears
"starting up"to"idle"only when no active run owns the status line —loadHistory()returning an adopted in-flight run, or a reconnect-ownedstreaming/running/finishing contextstatus, is left intact so active work is not hidden. The.catchstartup-failure path still clears to"idle"beforesetConnectionStatus("startup failed", 5000)sorenderStatus()takes the static-text branch for failure/ready states. The "starting up" claim itself is gated byresolveStartupActivityStatusso it never overwrites reconnect-owned streaming. The post-init ready status string and TTL are unchanged.Current review state
Next action: CI (including the Linux PTY shard) and maintainer review.
Waiting on: Linux CI to run the new PTY behavioral regression (not bootable on the contributor's Windows machine); maintainer review of the
onConnectedbusy-state clear-on-failure invariant.Bot/reviewer comments addressed: none yet (fresh PR).