Skip to content

feat: Wait keeps a thread working until its background command ends - #15315

Closed
t3dotgg wants to merge 2 commits into
mainfrom
t3code/running-command-working-status
Closed

t3dotgg wants to merge 2 commits into
mainfrom
t3code/running-command-working-status

Conversation

@t3dotgg

@t3dotgg t3dotgg commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Problem

A thread waiting on a long background command (for example a 50 minute benchmark run with Claude's run_in_background) shows as done. It does not go into the Working section, and the "Thread completed" alert fires when the turn ends. T3 Code treats every background command as one the agent left running, like a dev server (#14213, #14910), and the provider gives no signal that tells the two apart. Reported in #15099.

Change

Commands stay "left running" by default, so dev servers keep today's behavior. A new opt-in Wait marks the commands a thread runs now as ones to wait for. A held command holds the thread like a subagent does: the thread counts as working, it moves to the Working section, the strip reads "Waiting on command …", and the completion alert (desktop, web, and mobile push) waits until the command ends. Don't wait undoes it.

  • Server: new thread.background-work.hold command stores heldBackgroundTaskIds on the thread. The derived background work stamps held: true on those commands, and backgroundWorkHoldsCompletion treats them like subagents, so every surface that already reads that predicate follows.
  • Web: Wait / Don't wait next to Stop on the background work strip.
  • Mobile: tap the background status pill to wait or stop waiting.
  • Agents: wait_for_background_commands MCP tool, so an agent can hold a command it starts mid-turn.
  • Version skew: gated on a new threadBackgroundWorkHold server capability. Old clients ignore the new optional field and skip the new event type.
  • The web completion alert re-arms while a thread waits, so held work that ends without a new turn still alerts once.

No system prompt change: telling every agent about the tool would grow every prompt and change replay fixtures. The tool description carries the guidance.

Scope and approval

Theo asked for this opt-in ("don't come back until this is done running") in the session that made it. This is option 2 from #15099.

Verification

  • Real dev client, Claude Sonnet 5.5: the agent started a 4 minute background command. The row showed no work and the strip read "Running: …" with Wait. After Wait, the row read "Waiting" and the strip "Waiting on command …". Don't wait reverted it. When the command ended, Claude woke, finished, and the strip cleared.
  • MCP tool: Claude started a background command, called wait_for_background_commands mid-turn, and after the turn the thread read "Waiting". It woke and finished when the command ended.
  • Tests: hold / release / reject in Orchestrator.backgroundWorkHold.test.ts (SQL shell path), held stamping and ungated collection in shared, strip state in client-runtime, and a coordinator test that fails without the alert re-arm.
  • Not checked on a native mobile device. Mobile typechecks.
Before Wait After Wait
Before: row shows no work, strip reads Running with a Wait button After: row reads Waiting, strip reads Waiting on command with Don't wait

Reviewed with sol-loop: 3 rounds with GPT-6.1 Sol on high.

Created with Claude Opus 5.5 in T3 Code (Claude Code harness).

🤖 Generated with Claude Code

Fixes #15099

A background command reads as left running, like a dev server, so a thread
waiting on a long benchmark showed as done. Wait on the command strip (or
the wait_for_background_commands MCP tool) holds the thread's running
commands: it stays in Working, its completion alert waits, and Don't wait
undoes it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Oct 3, 2026
@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 3, 2026
Comment thread packages/shared/src/t3McpToolPresentation.ts
Comment thread apps/server/src/mcp/toolkits/thread/handlers.ts Outdated
@github-actions

github-actions Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

⚠️ The thread fixture changed, so impact percentages are not directly comparable to the main baseline.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 4.9 KiB — 6.8 KiB ✅
Codex Thread snapshot wire — 3.7 KiB — 4.9 KiB ✅
Codex Live turn WebSocket wire — 1.1 KiB — 2.0 KiB ✅
Codex Live turn WebSocket decoded — 20.4 KiB — 29.3 KiB ✅
Codex Live turn messages — 1 — 8 ✅
Claude Total thread wire — 4.9 KiB — 6.8 KiB ✅
Claude Thread snapshot wire — 3.7 KiB — 4.9 KiB ✅
Claude Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Claude Live turn WebSocket decoded — 20.8 KiB — 29.3 KiB ✅
Claude Live turn messages — 2 — 8 ✅

Baseline: 408ff8a · PR result: f844ef9 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 106.1 KiB
  • Claude decoded thread snapshot: 106.4 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeapp Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR adds a new MCP and UI workflow that persists background-command holds and changes thread status, sidebar placement, awareness, and completion notifications across web and mobile. It also enables the capability in the default server configuration, so the cross-cutting runtime behavior should receive human review.

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

The wait_for_background_commands tool reported every dispatch failure as
"no background command running". The orchestrator now rejects that case
with its own error tag, and other failures stay retryable. Tool labels are
neutral, since the same tool also stops waiting, and the work-log summary
reads the wait input. Also fixes a test literal that failed typecheck.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 3, 2026

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

🧰 Additional context used
📚 Code guidelines (2)
docs/internals/effect-services.md — configured
AGENTS.md — auto-discovered

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: pingdotgg/t3code/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Team
  • Run ID: 46756671-47fa-49a1-985f-d7df088c8acd
📥 Commits

Reviewing files that changed from the base of the PR and between 429c625 and f844ef9.

📒 Files selected for processing (32)
  • apps/mobile/src/features/threads/ThreadDetailScreen.tsx
  • apps/mobile/src/features/threads/ThreadRouteScreen.tsx
  • apps/mobile/src/features/threads/floating-working-control.tsx
  • apps/mobile/src/features/threads/floating-working-status.ts
  • apps/server/src/environment/ServerEnvironment.ts
  • apps/server/src/mcp/toolkits/thread/handlers.ts
  • apps/server/src/mcp/toolkits/thread/tools.ts
  • apps/server/src/orchestration-v2/Orchestrator.backgroundWorkHold.test.ts
  • apps/server/src/orchestration-v2/Orchestrator.ts
  • apps/server/src/orchestration-v2/ProjectionMaintenance.ts
  • apps/server/src/orchestration-v2/ProjectionStore.ts
  • apps/server/src/orchestration-v2/testkit/OrchestratorScenario.ts
  • apps/server/src/relay/AgentAwarenessRelay.ts
  • apps/web/src/components/ChatView.tsx
  • apps/web/src/components/Sidebar.logic.ts
  • apps/web/src/components/ThreadNotificationCoordinator.test.tsx
  • apps/web/src/components/ThreadNotificationCoordinator.tsx
  • docs/user/thread-sidebar.md
  • packages/client-runtime/src/operations/commands.ts
  • packages/client-runtime/src/state/models.ts
  • packages/client-runtime/src/state/orchestrationV2Projection.ts
  • packages/client-runtime/src/state/threadCommands.ts
  • packages/client-runtime/src/state/threadExecution.test.ts
  • packages/client-runtime/src/state/threadExecution.ts
  • packages/client-runtime/src/t3ToolSummary.test.ts
  • packages/client-runtime/src/t3ToolSummary.ts
  • packages/client-runtime/src/work-log/presentation.ts
  • packages/contracts/src/environment.ts
  • packages/contracts/src/orchestrationV2.ts
  • packages/shared/src/orchestrationV2PendingBackgroundWork.test.ts
  • packages/shared/src/orchestrationV2PendingBackgroundWork.ts
  • packages/shared/src/t3McpToolPresentation.ts

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


📝 Walkthrough

Walkthrough

The change adds a way to hold or release currently running background commands. Server state and client presentations track held commands, and web, mobile, and MCP surfaces expose the corresponding actions.

Changes

Background command wait

Layer / File(s) Summary
Held-task contract and derivation
packages/contracts/src/environment.ts, packages/contracts/src/orchestrationV2.ts, packages/shared/src/orchestrationV2PendingBackgroundWork.ts, packages/shared/src/orchestrationV2PendingBackgroundWork.test.ts
Contracts add the capability, held-task state, command, and event. Shared derivation marks matching command tasks as held and makes only held commands hold completion.
Server hold command and event projection
apps/server/src/environment/ServerEnvironment.ts, apps/server/src/orchestration-v2/*, apps/server/src/relay/AgentAwarenessRelay.ts, apps/server/src/mcp/toolkits/thread/*
The server handles hold and release requests, updates thread state without changing updatedAt, and projects and publishes the event. The MCP toolkit exposes wait_for_background_commands.
Client command and runtime state
packages/client-runtime/src/operations/commands.ts, packages/client-runtime/src/state/*
Client runtime dispatches hold commands, updates pending command state optimistically, and derives a wait, release, or null presentation action.
Client controls and completion alerts
apps/web/src/components/ChatView.tsx, apps/web/src/components/ThreadNotificationCoordinator*, apps/web/src/components/Sidebar.logic.ts, apps/mobile/src/features/threads/*, packages/shared/src/t3McpToolPresentation.ts, packages/client-runtime/src/t3ToolSummary*, packages/client-runtime/src/work-log/presentation.ts, docs/user/thread-sidebar.md
Web and mobile add conditional wait and release controls. Notification handling, tool summaries, sidebar status text, and user documentation cover background-command waiting.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Feature · Severity of issue fixed: Low

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant OrchestratorV2
  participant ProjectionStore
  Client->>OrchestratorV2: Dispatch thread.background-work.hold
  OrchestratorV2->>ProjectionStore: Apply thread.background-work-held event
  ProjectionStore-->>Client: Return thread state with held task IDs
Loading

Suggested reviewers: juliusmarminge

Merge Risk: ⚪ Minimal · up to f844e

Wait should defer completion alerts until the held command finishes. No actionable issue was established that prevents merging after normal checks.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning For #15099, the PR adds a reversible hold command, UI controls, and completion-alert re-arming. Held commands then hold completion. However, commands remain unheld by default, and the new MCP tool onl… Ensure commands that the agent is waiting on are marked held without requiring a separate explicit hold call, or otherwise ensure the issue’s waiting scenario cannot trigger a completion alert. Add coverage for that scenario.
Docstring Coverage ⚠️ Warning Docstring coverage is 31.82% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 31 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: an opt-in wait keeps a thread working until its background command ends.
Description check ✅ Passed The description covers the problem, cross-component changes, scope rationale, verification results, and screenshots. It states that Theo requested the opt-in and links the related issue, but does not …
Out of Scope Changes check ✅ Passed The server command, MCP tool, contracts, shared completion logic, web and mobile controls, alert handling, tests, and documentation all support the background-command wait behavior requested by #15099…
Full details: Linked Issues check

Explanation

For #15099, the PR adds a reversible hold command, UI controls, and completion-alert re-arming. Held commands then hold completion. However, commands remain unheld by default, and the new MCP tool only works when the agent explicitly calls it. A background command that the agent waits for but that is not explicitly held can still trigger the premature alert. This does not meet the issue’s expected behavior for waiting commands. The issue’s option 2 also specifies waiting by default, unlike this implementation.

Full details: Docstring Coverage

Explanation

Docstring coverage is 31.82% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 31 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

sandscooling pushed a commit to sandscooling/t3code that referenced this pull request Oct 3, 2026
…its background command ends)

Carried until it lands upstream. A held background command (Wait on the
background work strip, or the wait_for_background_commands MCP tool)
holds its thread like a subagent: Waiting in the sidebar, counted in the
project group's active number, and the completion alert waits for it.

Three keep-both conflicts: the fork's background clock beside the new
Wait button in ChatView, and two test files. Two of the PR's new tests
adapted to fork behaviour, each marked: a completion alerts with its
sound and no toast, and background tasks carry startedAt.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
sandscooling pushed a commit to sandscooling/t3code that referenced this pull request Oct 4, 2026
Fork slimming, lane 8 of the 2026-10-03 audit. The fork's session tools
internals and glossary rows move to docs/internals/fork-session-tools.md,
the Claude output styles section to docs/user/claude-output-styles.md, and
the sidebar text for spawned sessions into agent-orchestration.md, which
now also describes crew sessions reading Idle with quiet completions.
providers.md, glossary.md and providers-claude.md match upstream again;
thread-sidebar.md keeps only carried PR pingdotgg#15315's own section. The README's
renaming bullet names the real setting.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@t3dotgg t3dotgg closed this Oct 5, 2026
sandscooling pushed a commit to sandscooling/t3code that referenced this pull request Oct 6, 2026
44 upstream commits. The fork's plan progress meter collided with upstream
pingdotgg#15907 and is deleted whole (Kevin ruled it expendable). Carried pingdotgg#15315 is
closed upstream but kept: its held commands compose with pingdotgg#16204's PR-watch
holds. ThreadNotificationCoordinator gains awaitsAnswer so pingdotgg#15033's
unchanged-shell skip no longer closes standing answer toasts. Fork files move
from effect/unstable/* to effect/* for Effect 4.0.1.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
sandscooling pushed a commit to sandscooling/t3code that referenced this pull request Oct 6, 2026
pingdotgg#15315

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: A Claude thread waiting on a background command sends a false "Thread completed" alert

2 participants