fix(web): Keep running, stopped, and failed rows visible in the work log - #4762
fix(web): Keep running, stopped, and failed rows visible in the work log#4762mwolson wants to merge 331 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
caf6f38 to
d30b4a7
Compare
5a7eae3 to
257f810
Compare
257f810 to
365949a
Compare
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This range contains a 331-commit, 955-file orchestration V2 migration with new production workflows, persistence migrations, public API changes, authentication updates, and mobile/server integrations—not just the stated web work-log fix. Unresolved timeline rendering issues and the added product-default and static-analysis override changes add further review risk. Not approved because:
Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more. |
Dismissing prior approval to re-evaluate 7d5e55c
Retain pending admission after transient status failures and use one generation-owned retry worker. Ignore stale timers and duplicate evidence so older prompts cannot finish newer steering. Finding: R14 status reconciliation Model: GPT-5.6 Sol via Codex
Keep hidden local and inherited rows from consuming history pages. Preserve stop-request dependencies, source-run cutoffs, and imported history while loading related metadata from the selected cohort and using indexed watermark lookups. Finding: P01 bounded history visibility Model: GPT-5.6 Sol via Codex
Adapt grouped tool summaries and the floating working timer to V2 run, attempt, and queue state. Bring over the composer, keyboard, and disclosure transitions while retaining the V2 activity inspector and queue controls. Keep OV2 web composer and grouping behavior intact; share only the existing command label parser with mobile.
Restores main features dropped by the policy replay: pingdotgg#8569 theme wiring, pingdotgg#8850 composer banner follow-ups, pingdotgg#8855/pingdotgg#8904 composer fixes, pingdotgg#8831 settings search rework, pingdotgg#8803 workspace-mutation refresh (v2-adapted), pingdotgg#8840 circle-alert, pingdotgg#8584 codex artifact templates, pingdotgg#8688/pingdotgg#8807/pingdotgg#8936 video + image previews (web and mobile, v2-adapted), pingdotgg#8862 Expo glass, and the round's docs. Timeline thinking rows (pingdotgg#8984) stay on the v2 work-live system. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
a6e0049 to
50a57b6
Compare
The v2 equivalents of main's pingdotgg#8984 and pingdotgg#8922: a "Working for ..." header anchors the active run, the trailing live tool row survives between actions in past tense instead of vanishing, and a shimmering Thinking row marks reasoning gaps. During workspace preparation the header shows "Setting up worktree..." (driven by the local dispatch flag or the v2 run's preparing status, so remote viewers see it too), the composer footer span is gone, and draft promotion waits until the run starts or startup fails instead of navigating mid-preparation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
38109f8 to
a9f243a
Compare
Dismissing prior approval to re-evaluate a9f243a
| if ( | ||
| entry.id !== group.terminalEntry?.id && | ||
| !timelineEntryIsPersistentResourceCard(entry) && | ||
| !timelineEntryIsTerminalError(entry) |
There was a problem hiding this comment.
🟡 Medium chat/MessagesTimeline.logic.ts:783
A failed itemType: "error" with tone: "info" is rendered as a generic work-toggle instead of a work error row, so the provider error detail remains hidden and the expected provider-error-entry row never appears. deriveTurnFolds now leaves these entries visible, but the rendering branch only recognizes tone === "error"; update that branch to also recognize timelineEntryIsTerminalError.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/chat/MessagesTimeline.logic.ts around line 783:
A failed `itemType: "error"` with `tone: "info"` is rendered as a generic `work-toggle` instead of a `work` error row, so the provider error detail remains hidden and the expected `provider-error-entry` row never appears. `deriveTurnFolds` now leaves these entries visible, but the rendering branch only recognizes `tone === "error"`; update that branch to also recognize `timelineEntryIsTerminalError`.
There was a problem hiding this comment.
Two of these findings look like fallout from rebasing onto t3code/codex-turn-mapping: the collapsed work-log UI this PR's round-4 repair targets (a per-group visible cap and a "+N previous tool calls" expander) does not exist on this base, so the new selector, its constant, and the component tests written against it have nothing to attach to.
Posted via Macroscope — UI Consistency
| structuredPayload: { status: row.itemStatus } as OrchestrationV2TurnItem, | ||
| }, | ||
| }; | ||
| }); | ||
|
|
||
| // Collapsed groups used to keep only slice(-1), so a later completed tool | ||
| // buried the running or stopped row the work-log filter retained. | ||
| it("keeps pinned running and stopped tools visible in a collapsed work group", () => { | ||
| const runningAndCompleted = renderToStaticMarkup( | ||
| <MessagesTimeline | ||
| {...buildProps()} | ||
| timelineEntries={multiToolWorkEntries([ | ||
| { id: "running", label: "Active shell", itemStatus: "running" }, | ||
| { id: "completed", label: "Finished shell", itemStatus: "completed" }, | ||
| ])} | ||
| />, | ||
| ); | ||
| expect(runningAndCompleted).toContain("Active shell"); | ||
| expect(runningAndCompleted).toContain("Finished shell"); | ||
| expect(runningAndCompleted).toContain("lucide-loader-circle"); | ||
| expect(runningAndCompleted).not.toContain("previous tool"); | ||
|
|
||
| const stoppedAndCompleted = renderToStaticMarkup( | ||
| <MessagesTimeline | ||
| {...buildProps()} | ||
| timelineEntries={multiToolWorkEntries([ | ||
| { id: "stopped", label: "Interrupted shell", itemStatus: "interrupted" }, | ||
| { id: "completed", label: "Finished shell", itemStatus: "completed" }, | ||
| ])} | ||
| />, | ||
| ); | ||
| expect(stoppedAndCompleted).toContain("Interrupted shell"); | ||
| expect(stoppedAndCompleted).toContain("Finished shell"); | ||
| expect(stoppedAndCompleted).toContain(', stopped"'); | ||
| expect(stoppedAndCompleted).not.toContain("previous tool"); | ||
| }); | ||
|
|
||
| it("does not pin pending or waiting rows in a collapsed work group", () => { | ||
| const markup = renderToStaticMarkup( | ||
| <MessagesTimeline | ||
| {...buildProps()} | ||
| timelineEntries={multiToolWorkEntries([ | ||
| { id: "pending", label: "Queued shell", itemStatus: "pending" }, | ||
| { id: "waiting", label: "Blocked shell", itemStatus: "waiting" }, | ||
| { id: "completed", label: "Finished shell", itemStatus: "completed" }, | ||
| ])} | ||
| />, | ||
| ); | ||
|
|
||
| expect(markup).toContain("Finished shell"); | ||
| expect(markup).not.toContain("Queued shell"); | ||
| expect(markup).not.toContain("Blocked shell"); | ||
| expect(markup).toContain("+2 previous tool calls"); |
There was a problem hiding this comment.
These collapsed-work-group cases assert against UI that does not exist on this target branch. Work groups render row.summary through WorkGroupToggleTimelineRow (e.g. Ran 2 commands), there is no +N previous tool calls expander string anywhere in MessagesTimeline.tsx, and no per-group visible cap that could hide Queued shell/Blocked shell — so both the pinned-row and the not-pinned expectations fail rather than guarding the fix.
Suggest retargeting them at the work-live/work-toggle row model (or removing them alongside the unused selectCollapsedWorkLogEntries) so the suite matches the shipped work-group rendering.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a9f243a. Configure here.
| entry.id !== group.terminalEntry?.id && | ||
| !timelineEntryIsPersistentResourceCard(entry) && | ||
| !timelineEntryIsTerminalError(entry) | ||
| ) { |
There was a problem hiding this comment.
Collapsed groups hide pinned tool rows
High Severity
selectCollapsedWorkLogEntries is never used when building or rendering work groups. Settled groups still emit only a work-toggle that hides every row, so running and stopped tools stay behind the summary instead of remaining visible in the compact log. The +N previous tool calls expander the new tests expect is also never rendered.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit a9f243a. Configure here.
| entry.id !== group.terminalEntry?.id && | ||
| !timelineEntryIsPersistentResourceCard(entry) && | ||
| !timelineEntryIsTerminalError(entry) | ||
| ) { |
There was a problem hiding this comment.
Failed errors stay behind work toggle
Medium Severity
deriveTurnFolds now keeps failed itemType === "error" entries out of the turn fold, but row emission still treats projected provider errors as ordinary work because their tone is info. They become a work-toggle labeled Provider error, so the failure detail stays hidden unless the group is expanded.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit a9f243a. Configure here.
6081201 to
95bacdd
Compare
There was a problem hiding this comment.
The selectCollapsedWorkLogEntries selector plus its collapsed-group tests, and the unused workingStepLabel / pendingBackgroundTasks props, are still in the state described in the earlier threads on MessagesTimeline.logic.ts:76, MessagesTimeline.test.tsx:2557, and MessagesTimeline.tsx:243 — MAX_VISIBLE_WORK_LOG_ENTRIES now type-checks, but nothing in MessagesTimeline.tsx calls the selector and the shipped work group still renders every visible entry with no per-group cap or expander. Not re-raising those inline.
Posted via Macroscope — UI Consistency
| const workRow = (itemStatus: OrchestrationV2TurnItem["status"] | undefined) => { | ||
| const toolLifecycleStatus = toolLifecycleStatusForItemStatus(itemStatus); |
There was a problem hiding this comment.
These fixtures never reach SimpleWorkEntryRow, so the new lifecycle assertions do not exercise the indicators they describe. beforeEach resets activityTestState.expanded to false, and a tone: "tool" entry with a settled run (isWorking: false, latestRun: null) derives a collapsed work-toggle row (MessagesTimeline.logic.ts:1105), which renders only row.summary — no spinner and no lifecycle-suffixed aria-label. expect(markup).toContain("lucide-loader-circle") and toContain(', stopped"') therefore fail, while toContain("Ran command") passes only because that is also the group summary text.
The neighboring failed-marker case opts into the expanded path explicitly; suggest doing the same in this helper so the rows under test are the ones the PR changed:
| const workRow = (itemStatus: OrchestrationV2TurnItem["status"] | undefined) => { | |
| const toolLifecycleStatus = toolLifecycleStatusForItemStatus(itemStatus); | |
| const workRow = (itemStatus: OrchestrationV2TurnItem["status"] | undefined) => { | |
| activityTestState.expanded = true; | |
| const toolLifecycleStatus = toolLifecycleStatusForItemStatus(itemStatus); |
Posted via Macroscope — UI Consistency
|
Macroscope skipped reviewing this pull request. Per-review cost limit exceeded (workspace setting). This review would cost an estimated $248.57, which exceeds your per-review limit of $10.00. The top 3 files driving up this estimate:
Tip To get this pull request reviewed, you can:
|


What Changed
The web work log keeps the rows that tell you what a turn is doing. Running tools stay in the log with a spinner. Interrupted tools stay visible without a success check. Collapsed work logs still show an active or interrupted tool even when newer rows would have pushed it out.
When a provider fails and the turn has no assistant message, the failed error stays in the timeline instead of only the sidebar. Recovered retries still fold like ordinary work.
Why
The server already had the right items. The web timeline treated running and interrupted tools like noise. When a finished turn collapsed its work log, it kept a final assistant message but hid a failed error, so the error only showed in the sidebar.
This is web-only. Mobile does not share these filters.
UI Changes
Running and stopped tool rows remain visible, including in compact work logs. Failed provider errors remain visible on settled turns with no assistant message. Stopped tools have no extra glyph. The interrupt row still carries the stop marker.
No before/after screenshots. Checked on a Codex turn in the web app: a foreground command showed a spinner while running, and after Stop the row stayed without a spinner or success check. A live failed provider turn had the error folded away before this change.
Checklist
Note
Medium Risk
Large mobile thread/orchestration migration affects caching, runtime gating, and user-facing archive/stop behavior; removing the thread-transfer report workflow is low risk but changes PR observability for transfer regressions.
Overview
Removes the CI “thread transfer impact” PR comment pipeline by deleting
thread-transfer-report.ymland the trusted publisher scripts/tests that validated artifacts and upserted comparison comments. Server test shards can still uploadthread-transfer-resultsartifacts; nothing in this diff publishes them to PRs anymore.Mobile is moved onto shared V2 orchestration client-runtime paths. SQLite shell/thread caches now encode/decode via
StoredOrchestration*schemas andORCHESTRATION_CACHE_SCHEMA_VERSION, with tests forDateTimeround-trips. Connection wiring swaps inboundedThreadSnapshotLoaderLayerandthreadHistoryControllerLayer. Thread UI and actions follow projection/runtime models (useSelectedThreadProjection,thread.runtimevs legacysession,RuntimeRequestIdfor approvals/user input withresponseCapabilitygating). New or expanded UX includes thread queue control, relationships banner, activity inspector (files, rollback), visit watermark dispatch, andthreadCanArchiverules that allow archive when queued work has no active provider run. Review/checkpoints derive fromThreadCheckpointSummary/deriveThreadCheckpointSummaries.Smaller follow-ons: CI installs
build-essentialso ACP process-tree live tests always compile their pthread fixture; README links appearance docs; desktop exposesuserDataDirName/ legacy dir names in tests; marketing updates the Cursor harness label; mobile theme generator adds adaptive color tokens used by the new inspector surfaces.Reviewed by Cursor Bugbot for commit 05f47ec. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Keep running, stopped, and failed rows visible in the work log and build orchestration V2 foundation
derivePendingBackgroundWorkto derive a post-settlement pending-work roster from provider-thread tasks and nonterminal turn items, gating on latest-run settlement and excluding rolled-back itemsisOrchestrationV2TurnItemVisibleto hide items from rolled-back runs, queued user messages from cancelled runs, and unpaired superseded interruption resultsEnvironmentApireplaces the legacyorchestrationproperty withorchestrationV2, removing turn-diff and archived-shell methodsMacroscope summarized 05f47ec.