Skip to content

feat(clients): background work says what it is and which subagent finished - #13949

Merged
juliusmarminge merged 2 commits into
t3code/codex-turn-mappingfrom
v2/specific-background-work-clients
Sep 28, 2026
Merged

juliusmarminge merged 2 commits into
t3code/codex-turn-mappingfrom
v2/specific-background-work-clients

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Sep 27, 2026 •

Copy link
Copy Markdown
Member

Stacked on #13948, which makes the server name background work as a discriminated union. This PR shows it.

The composer strip said "Waiting on N background tasks" whether the work was a subagent, a shell command or a monitor, and it only listed raw descriptions or task ids. Mobile showed nothing at all once the turn settled. Timeline notification rows all used the same bolt icon and could not open the subagent that finished.

What changed

Every client decision switches on the union's kind, with a satisfies never default, so a new kind fails to compile until each switch handles it. No client or shared code reads provider taskType strings any more.

  • Shared title builder (presentPendingBackgroundWork in packages/client-runtime/src/state/threadExecution.ts): groups pending work by kind, subagents first. A subagent member's childThreadId becomes the item's link. A roster from before kinds existed arrives as background_task (the contracts fallback from feat(server): background wakes say which subagent, command, or monitor finished #13948), so it reads "background task".
  • Web composer strip: the title comes from the builder, and the description lists every item by name. A subagent's name is an InlineButton that opens its child thread, using the handler the timeline already uses. The long list keeps the banner's existing truncate-and-popover behavior. Stop is unchanged.
  • Mobile: the floating pill above the composer shows the same title once the turn settles (the thread shell's roster already reached mobile, but nothing rendered it). Its accessibility label lists each item. Stop is unchanged; mobile had no Stop for settled background work before this PR either.
  • Timeline notification rows (web and mobile): an icon per source.kind from the existing sets (web bot/terminal/eye, mobile hammer/command/eye, matching each surface's subagent and command rows). delegated_task uses the subagent icon, background_task keeps the bolt, and a failed outcome keeps the alert icon. A notification whose source is one subagent or one delegated task opens that thread (notificationChildThreadId): an "Open subagent" link on web next to the timestamp (the same slot as "Open chat" for created threads), and the whole row on mobile (like the rows in the mobile subagent group). The summary text itself comes from feat(server): background wakes say which subagent, command, or monitor finished #13948.

Before and after

I did not run a dev server, so there are no screenshots. The strings, from the shared builder and the #13948 replay fixtures:

Where Before After
Composer strip, one Claude background subagent Waiting on background task · Background subagent test Waiting on subagent Background subagent test · Background subagent test (opens the child thread)
Composer strip, two subagents and a command Waiting on 3 background tasks · Review src/math.ts, Write tests, npm test Waiting on 2 subagents and 1 command · Review src/math.ts, Write tests, npm test
Composer strip, one Claude background Bash Waiting on background task · Background sleep test Waiting on command Background sleep test
Mobile, same cases (nothing after the turn settled) the same titles in the floating pill
Timeline, Grok subagent finished [bolt] Background activity updated [bot] Subagent "Sleep then reply done" finished · Open subagent
Timeline, Grok monitor finished [bolt] Background activity updated [eye] Monitor "Watch three tick echoes" finished
Timeline, Claude TaskStop on an agent and its Bash [bolt] Background activity updated [bolt] Subagent "Agent B" and command "Sleep 60 seconds then echo B_DONE" were stopped (mixed kinds are background_task)
Timeline, a Codex command wake stored before #13948 [bolt] Background command finished [terminal] Background command finished (the stored background_command decodes as command)

Verification

  • packages/client-runtime: vp test run src/state/threadExecution.test.ts src/state/entities.test.ts: 50 passed. The presentation tests build union members only: single, grouped (with a subagent's child thread), and generic background_task titles.
  • apps/web: vp test run src/session-logic.test.ts src/components/chat/MessagesTimeline.logic.test.ts src/components/Sidebar.logic.test.ts: 320 passed. apps/mobile: vp test run src/lib/threadActivity.test.ts src/features/threads/floating-working-status.test.ts src/features/threads/threadListV2.test.ts: 173 passed.
  • tsc --noEmit for contracts, shared, server, client-runtime, web and mobile: clean. vp lint on touched files: no errors (it caught a toSorted that Hermes lacks, fixed); remaining warnings are pre-existing. vpr knip:check: clean.
  • Not run: a dev server, a browser, or a simulator, so no before/after images.

Model: Claude Opus 5.5 (Claude Code)

🤖 Generated with Claude Code

@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 Sep 27, 2026
Comment thread apps/mobile/src/lib/threadActivity.ts Outdated
function itemIcon(item: OrchestrationV2TurnItem): ThreadFeedActivity["icon"] {
if (item.type === "notification") return "zap";
if (item.type === "notification") {
switch (item.workKind) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium lib/threadActivity.ts:447

Failed notification items render the work-kind icon instead of alert, so failed subagent, command, and monitor notifications lose their failure indicator. itemIcon switches on workKind without checking item.outcome; return alert before that switch when the outcome is failed.

Suggested change
switch (item.workKind) {
if (item.outcome === "failed") {
return "alert";
}
switch (item.workKind) {
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/src/lib/threadActivity.ts around line 447:

Failed notification items render the work-kind icon instead of `alert`, so failed subagent, command, and monitor notifications lose their failure indicator. `itemIcon` switches on `workKind` without checking `item.outcome`; return `alert` before that switch when the outcome is `failed`.

@github-actions

github-actions Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

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: unavailable · PR result: 3382314 · 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 Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces cross-platform user-facing behavior for categorizing background work and navigating to subagent threads, rather than making a purely mechanical or isolated UI change. An unresolved medium-severity finding also indicates that failed mobile notifications can lose their failure icon.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

No code changes detected at 3382314. Prior analysis still applies.

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

juliusmarminge and others added 2 commits September 28, 2026 13:54
…ished

The composer strip said "Waiting on N background tasks" whether those were
subagents, shell commands or monitors, and mobile showed nothing once the
turn settled.

- A shared builder in client-runtime names the work, grouped by kind:
  "Waiting on subagent Review src/math.ts", "Waiting on 2 subagents and
  1 command". Rosters from servers without `kind` still classify by task type.
- Web: the strip lists every item, and a subagent's name opens its thread.
  Stop is unchanged.
- Mobile: the floating pill shows the same title after the turn settles.
- Timeline notification rows use an icon per kind (subagent, command,
  monitor), and a subagent's row opens its thread on web and mobile.

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

The composer strip, timeline icons and "Open subagent" read the kind and
child thread from the union members the server now sends. Clients no
longer map provider taskType strings, and a new kind fails to compile
until each switch handles it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@juliusmarminge
juliusmarminge force-pushed the v2/specific-background-work-clients branch from 2dd3671 to 3382314 Compare September 28, 2026 20:57
@juliusmarminge
juliusmarminge merged commit b9ffe49 into t3code/codex-turn-mapping Sep 28, 2026
25 checks passed
@juliusmarminge
juliusmarminge deleted the v2/specific-background-work-clients branch September 28, 2026 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

1 participant