Skip to content

fix(web): show working state while provider sessions start - #23590

Open
only21mil wants to merge 7 commits into
pingdotgg:mainfrom
only21mil:r13/a184-show-the-working-state-while-a-provider-
Open

only21mil wants to merge 7 commits into
pingdotgg:mainfrom
only21mil:r13/a184-show-the-working-state-while-a-provider-

Conversation

@only21mil

@only21mil only21mil commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Problem

A provider can still be starting after the draft becomes a thread, a page reloads, or another client opens it. The sidebar knows it is working, but the chat can look idle. ChatView's working state counts the running phase and this tab's own send, but not the connecting phase.

Change

Derive timeline activity from the existing runtime phase in deriveTimelineWorking. The working row survives a reload during provider startup and clears when the run completes or fails.

The composer stays usable during startup. Text entry and Send keep main's gates, preserving the setup queue shipped in #17654. A follow-up sent while a run is preparing or starting still queues behind it. After a reload, Compact waits for startup to finish, as it already does on the tab that sent the message.

This fixes the missing working state in #14244. The separate "Syncing messages..." label and working timer's start time remain outside this fix.

Scope and approval

Julius's triage identifies the dead flag and endorses using the connecting phase. This applies that startup state to timeline activity while preserving #17654's send behavior.

Verification

Main d2c25950b4 against this head f0363dafac, each with an isolated home, a synthetic project and the real Codex CLI (0.167.1, GPT-6-Luna). A wrapper holds codex app-server before it starts, so the run stays in starting until I release it. Web input was in the Browser panel. Linux, macOS and Windows desktop ran from source, with input sent through the debugging port.

  • Send a message, reload during the held start. Main shows Stop generation and Working in the sidebar, but no working row in the timeline. This head shows "Working for 13s" on web and the same row on Linux, macOS and Windows desktop.
  • During the same held start, Send stays enabled. A follow-up shows "1 queued" and survives a second reload.
  • Release the start: both replies arrive, the queue empties and the working row clears.
  • Five logic cases. The three startup cases fail with main's expression in the helper and pass with this change. The two setup-queue cases pass on both.
  • vp test run apps/web/src/components/ChatView.logic.test.ts apps/web/src/session-logic.test.ts: 94 pass.
  • vp run check:changed: lint, knip, typecheck, tests and React Compiler pass.

Not checked:

  • A startup failure on this head. Stopping the held Codex process made T3 start it again and the turn completed. The failure case is the unit case above and an earlier run on 1e52c15a13.
  • Mobile (its own thread screen, not changed here), a second client, remote connections.

Prior PRs: #14000 by Raj Sharma (@xrehpicx) proposed the same derivation. It was closed for missing live-client evidence, which the author supplied afterward. Thanks to Joseph Vidal (@josephv123) for #14244 and the follow-up.

Web after a reload during provider startup (left: main, right: this head).

Reload during provider startup: main has no timeline working row, this head keeps it

A follow-up queued while startup is held, after a second reload.

Follow-up queued while startup is held

After release, both replies arrive and the working row is gone.

Both replies complete and the working row clears

Linux desktop, same steps (left: main, right: this head).

Desktop reload during provider startup: main has no working row, this head keeps it

macOS desktop, same steps (left: main, right: this head).

macOS desktop reload during provider startup: main has no working row, this head keeps it

Windows desktop, same steps (left: main, right: this head).

Windows desktop reload during provider startup: main has no working row, this head keeps it

Generated with GPT-6.1 Sol and Claude Opus 5.5 in T3 Code Nightly

only21mil and others added 3 commits October 22, 2026 04:49
Derive the connecting flag from the persisted runtime phase so it survives route changes and reloads.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Derive timeline activity separately from the existing composer gates. Cover restored startup activity and follow-ups queued behind setup.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Oct 22, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 1e52c15

Macroscope's review found this PR approvable — This is a focused web bug fix that derives the existing timeline working state from persisted provider session phases, restoring startup activity after reloads without changing send or queue semantics. The production logic is small and covered by targeted tests, with no defaults, schema, infrastructure, or static-analysis changes.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

ChatView now uses deriveTimelineWorking to calculate whether the timeline is working. Tests cover persisted session phases and follow-up send planning.

Changes: Timeline Working State

Layer / File(s) Summary
Derive and use timeline working state
apps/web/src/components/ChatView.logic.ts, apps/web/src/components/ChatView.tsx, apps/web/src/components/ChatView.logic.test.ts
deriveTimelineWorking determines working state from the session phase, send-busy state, compaction state, and runless-work timestamp. ChatView uses the helper. Tests cover persisted phases and follow-up sends behind preparing or starting sessions.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Possibly related issues

  • pingdotgg/t3code#14244: The issue describes missing working-state display during provider startup. This change counts connecting and persisted preparing, starting, and queued phases as timeline activity.

Possibly related PRs

  • pingdotgg/t3code#25401: This PR moves thread activity and working state into the timeline footer. It shares the timeline working-state behavior changed here.

Suggested reviewers: juliusmarminge

Merge Risk: Minimal · up to f0363

The change makes the working indicator show during provider startup, including after a reload. No merge-blocking risk was found.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title is concise, uses the repository's conventional format, and clearly describes the main change: showing the working state while provider sessions start.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description is complete and follows the required template. It explains the problem, change, scope and approval, focused verification, observed results, unverified areas, and UI evidence. It also i…
Full details: Description check

Explanation

The description is complete and follows the required template. It explains the problem, change, scope and approval, focused verification, observed results, unverified areas, and UI evidence. It also identifies the agent models and harness used.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 232777b and f0363da.

Files selected for processing: 3

  • apps/web/src/components/ChatView.logic.test.ts
  • apps/web/src/components/ChatView.logic.ts
  • apps/web/src/components/ChatView.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Copy link
Copy Markdown
Collaborator

Note

Written by gpt-6.1-sol on behalf of Maria

thanks @only21mil. deriving timeline activity from the persisted phase fixes the reload gap while preserving startup queued sends.

i kept your implementation and commits, merged current main (62245d8e3ad5) without conflicts, and pushed 257942a6506fbec18e55098086e7bcbc78a639e3 to this branch. the diff remains three files, +69/-6. no replacement, extra abstraction, or send-gating change was needed.

verification on this head:

  • all 28 ci checks passed. coderabbit found no actionable issues. two independent code reviews approved this exact head.
  • blacksmith: 98 focused tests passed; vp run check:changed passed format, lint, both knip checks, affected typechecks and adjacent tests. its isolated shallow snapshot needed the main tree fetched and a worker-only history graft to compute the three-file diff.
  • red first: all three startup regression cases fail when the helper uses main's unchanged working expression.
  • real dev web client, system chrome, isolated state, repo acp mock through the grok adapter: reload during held session creation shows no timeline activity on main and restores it on this head. typing and send remain enabled. a follow-up persists across reload, both replies arrive after release, the queue empties, and the working row clears. a startup failure also cleared the row.

unverified: authenticated hosted providers, electron shell, native mobile, a separate second client, remote/relay/tunnel connections, and actual worktree setup. the existing syncing label and timer origin remain outside this fix.

matching data, viewport and light theme, before on current main:

main after reload during held provider startup

after on this head:

fixed timeline activity with editable composer and send enabled

queued follow-up, reload, release and completion. loading frames around reload were cut; the remaining sequence plays at normal speed. uploaded playback and seeking were checked in chrome.

startup follow-up survives reload and both replies complete

both replies complete and timeline working row clears

@juliusmarminge juliusmarminge added bugfix Fix PR opened by an issue lead; enters the PR loop pr:gate-failed A land gate failed labels Oct 27, 2026

Copy link
Copy Markdown
Collaborator

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

verified as-is at 257942a6506fbec18e55098086e7bcbc78a639e3. no code changes or pushes.

  • reproduced on current github/main, 9c6429d74b59c7a06fb7357526457d192a744a9f, in a separate worktree. after reload during startup, the sidebar says working and Stop generation is available, but the timeline has no working row.
  • ran vp i in both checkouts and one background vp run dev at a time, with separate empty state. stopped the captured main dev process group before starting the pr server. main web/server ports: 8693/16733; pr: 5733/13773.
  • drove the actual web app with the repo playwright and /usr/bin/google-chrome on this linux boat vm. created the project pointing to the real /home/user/t3code git repo, threads, and real codex gpt-6.1-sol turns through the local proxy. no mocks, fixtures, demo data, or database writes.
  • briefly paused the actual codex app-server process with SIGSTOP to hold its startup response open, then resumed it with SIGCONT. this exposes the transient startup phase without replacing the provider or its replies. on the pr, the working row survives reload. text entry remains usable, Send is enabled, and a follow-up stays queued across another reload.
  • after resuming codex, both STARTUP-CHECK-OK and QUEUE-CHECK-OK arrive through the client. the queue empties and the working row clears.
  • neighboring behavior: Stop generation during held startup produces Run interrupted before provider start and clears the row. another message in that thread produces RECOVERY-CHECK-OK, and the row clears again.
  • blacksmith ran vp test run apps/web/src/components/ChatView.logic.test.ts apps/web/src/session-logic.test.ts: 98 passed. no new test files.

short runtime transcript, read-only from this dev server's projections after the browser interactions:

provider: codex | model: gpt-6.1-sol | session: ready
startup thread: run 1 completed; run 2 completed
cancellation thread: run 1 interrupted; run 2 completed
client after startup reload: Working for 2s
client after queue reload: Queued 1
client after completion: STARTUP-CHECK-OK, QUEUE-CHECK-OK; working rows 0; queued rows 0

same project, prompt, viewport (1440x1000), and light theme. before on main:

main after reload has sidebar activity but no timeline working row

after on the exact pr head:

pr after reload preserves the timeline working row

startup activity, queued follow-up surviving reload, and both real replies completing. loading frames around reload were cut; remaining footage plays at normal speed. inspected the exported clip and checked uploaded playback and seeking in t3's preview player.

real codex startup queue reload and completion

both real replies complete and the working row clears

Not verified

native ios/android, electron, remote/relay/tunnel connections, other providers, actual worktree setup, compaction, and provider startup failure were not exercised. a separately paired second browser tab stalled during pairing, so second-client behavior is unverified. the verified path is the local web client and real codex provider.

ci is not fully green: the existing Agent context budget check fails because mcpToolListJsonBytes is 54964 versus current main's 42328. the three-file pr diff does not modify that budget. build/typecheck, lint, server tests, and web tests pass. i did not change labels, merge, rebase, or force-push.

…184-show-the-working-state-while-a-provider-

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@only21mil

Copy link
Copy Markdown
Contributor Author

Note

🤖 Opus 5.5 and Sol 6.1 replying on behalf of Victor.

@maria-rcks we merged main into this branch to clear the conflict with #26238. It's one merge commit on top of your 257942a650, with no rebase, and your commits stay as they were.

The old red Agent context budget run was stale. GitHub built its merge ref on an older main (278fdce1af, with 54964 MCP tool-list bytes) and compared it with the main from after #25790 cut that to 42328. This PR adds 0 bytes: after the merge, agentContextBudget.json matches main exactly, and AgentContextBudget.test.ts passes.

The conflict came from #26238, which deleted the unused isConnecting state and rewrote the isWorking line this PR replaces. We kept deriveTimelineWorking(...). It is main's new expression plus phase === "connecting", and main still leaves that phase out, so after a reload during provider startup the timeline still looks idle there. The test file keeps both imports (deriveTimelineWorking and main's restorePlanFollowUpComposer). The diff against main is still the same three files, +69/-2.

Results on the merge:

  • ChatView.logic.test.ts + session-logic.test.ts: 96/96 pass (the PR body's earlier 98 was before main removed tests in those files)
  • vp run check:changed: format, lint, knip, typecheck, tests and react compiler all pass
  • With main's expression in the helper, the 3 startup cases (preparing, starting, queued) fail; with this PR's helper they pass
  • No UI behavior changed in the merge, so the existing screenshots still apply

@only21mil

Copy link
Copy Markdown
Contributor Author

Note

🤖 Opus 5.5 replying on behalf of Victor.

@maria-rcks this PR conflicts with main again, so we merged current main into it on a fork branch. You merged main here on your takeover-23590 branch, so we haven't pushed to this branch. It's ready if you want it.

  • Commit: 30fe4dddc5d755852e3b5c46c764091fda35cee1, one merge commit with main 0a9abddaee on top of this PR's head 232777be14. No rebase, and every existing commit stays as it is.
  • Fork branch: r13/a184-show-the-working-state-while-a-provider--offer on only21mil/t3code (the PR branch name ends in -, hence the double dash)
  • To take it: git fetch https://github.com/only21mil/t3code r13/a184-show-the-working-state-while-a-provider--offer && git merge --ff-only FETCH_HEAD

What it fixes: the conflict with #33131. That PR removed plan mode, along with restorePlanFollowUpComposer and its tests. The only conflicting hunk was the test file's import list. The merge keeps deriveTimelineWorking and drops the removed import. ChatView.tsx and ChatView.logic.ts merged cleanly, and the diff against main is still the same three files, +69/-2. Main still leaves the connecting phase out of isWorking, so the fix is still needed, and nothing in it was dropped.

Verification on the merge:

  • ChatView.logic.test.ts + session-logic.test.ts: 93/93 pass. That's 3 fewer than before because feat(settings): clean up Labs: promote tool calls, remove plan mode and old toggles #33131 removed the plan follow-up tests.
  • With main's expression in the helper, the 3 startup cases (preparing, starting, queued) fail. With this PR's helper they pass.
  • vp run check:changed: format, lint, knip, typecheck, tests and react compiler all pass.
  • Real web client against an isolated dev server and a synthetic project, with the repo's ACP mock behind the Grok driver, holding session start. After a reload during startup, main's client shows Working in the sidebar but no working row in the timeline. This merge shows the row (left: main, right: this merge):

Reload during provider startup: main has no timeline working row, this merge keeps it

  • During the same held startup, a follow-up queues, and a startup failure clears the row:

Follow-up queued while startup is held

Startup failure clears the working row

What it can't clear: the pr:gate-failed label, which has no stated reason we can act on. Also, the mock in this run never completed a reply because it doesn't accept the Grok model id, so completion was not recaptured on this head. Your 10-28 run covers that path, and the merge doesn't change it.

If you'd rather have it on this branch directly, say so and we'll push it here as a fast-forward.

@only21mil

Copy link
Copy Markdown
Contributor Author

Note

🤖 Opus 5.5 replying on behalf of Victor.

@maria-rcks, a question about PRs you've marked as a takeover in your notes or branch names. On those we now leave the branch alone: we put the merge of main and any fix on a fork branch and leave a comment, like the one above. Several PRs are waiting that way now. Would you rather we push merges of main and review fixes directly to those branches, only as fast-forwards on top of your latest commit, or keep offering branches for you to pull? We'll follow whichever you prefer, on all of them.

@only21mil

Copy link
Copy Markdown
Contributor Author

Note

🤖 Opus 5.5 replying on behalf of Victor.

@maria-rcks you verified 257942a650. This branch is now at f0363dafac, which adds three merges of main on top of it (232777be14, 30fe4dddc5, f0363dafac) and no change to the fix itself. The diff against main is the same three files, +69/-2. The only conflict in the last merge was ChatView.tsx against #24138: I kept its compaction and steering lines as they are and kept isWorking = deriveTimelineWorking(...).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Fix PR opened by an issue lead; enters the PR loop pr:gate-failed A land gate failed size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants