# fix\(mobile\): fold subagent lifecycle rows into one batch per spawn · PR \#10211 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/10211)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: t3code/mobile-subagent-spawn-batches

Target branch: t3code/mobile-work-row-expand-only-with-extra

Head commit: a83379df0175a23b22518b52fcb7f968248f4935

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/10211)

[Commits](https://git.cafe/pingdotgg/t3code/pull/10211/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/10211/diffs?format=markdown)

## Description

---

Stacked on #10210.

## Problem

Each subagent's progress and completion rendered as its own timeline row on mobile (three agents → three "Running …" rows plus their completions), while web folds a turn's spawns into one "Kicked off N subagents" row via `collapseDerivedWorkLogEntries` in `session-logic.ts`.

## Fix

Mirror web's batching in the mobile work log:

- Same spawn-group keys (`wf:<coordinator>` for workflows, `direct:<turn>` for direct spawns), decided at the first row seen per `taskId` so later rows under synthetic turns cannot splinter the batch.
- Agent lifecycle rows pass the agent-internal filter even when bypassed or owned by another agent, as on web; that is how Codex children (all bypassed) and Claude workflow members reach the batch row.
- The batch row keeps the anchor's identity so it renders where the run launched.
- Background tasks (`agentKind !== "agent"`) keep one row per task, as before.
- Web reads live agent state from its Agents panel; mobile has no such surface, so the row carries each member's latest lifecycle state, derives its own lifecycle from them (live while any member is, then the worst terminal state), and lists the members when opened. A Codex child's `idle` turn end counts as finished, and a finished coordinator settles members that never reported their own end. That lifecycle feeds the group summary and shimmer from #10173 unchanged.

## Verification

- `vp test run apps/mobile/src/lib/threadActivity.test.ts` — 98 passed, including new tests that fold two direct spawns into one row and track it through running → one done → one failed, fold bypassed workflow members into the coordinator's batch and settle them with it, and finish a Codex child on `idle`; plus updated expectations for the resumed-agent and Antigravity batch cases.
- `tsc --noEmit` for `apps/mobile`, targeted lint and format.
- Simulator, same seeded turn (three agents: two running, one finished) on `main` and this branch.

![Before: three separate subagent rows. After: one "Kicked off 3 subagents · 1 working" row.](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/17250a124edb0790/pair-batch.png)

Implemented by Claude Fable 5 in the Claude Code harness.


<!-- Macroscope's pull request summary starts here -->
<!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. -->
<!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. -->
> [!NOTE]
> ### Fold subagent lifecycle rows into one batch row per spawn in mobile `threadActivity`
> - Replaces one-row-per-agent-task rendering with one aggregated row per workflow or direct-spawn batch in the mobile work log; shell, monitor, and plan tasks remain ordinary per-task rows.
> - Agent task rows that were previously filtered as internal now reach feed derivation so they can be grouped by workflow, turn, or task ID into spawn batches.
> - Adds helpers for batch lifecycle precedence (in-progress > failed > stopped > completed), member merging by task ID, label generation with live/failed/stopped member counts, and expanded-body formatting listing each member's title, status, and detail.
> - Workflow coordinators are excluded from displayed member counts and details; a terminal coordinator settles unfinished workflow members to its own terminal state.
> - Updates tests in [threadActivity.test.ts](https://github.com/pingdotgg/t3code/pull/10211/files#diff-8fc154ca47cb1e024c4e1f266b22114cd6071c6cdac94118a62011bf81c3ccd2) to assert batch-row grouping, anchor identity, member counts, terminal states, and idle-as-completed behavior.
> - Behavioral Change: `isAgentInternalActivity` now retains agent task rows with task IDs (including bypassed rows) for batch folding instead of filtering them; consumers of `collapseDerivedWorkLogEntries` will see fewer rows and new structured spawn metadata on `WorkLogEntry`.
>
> <!-- Macroscope's review summary starts here -->
>
> <sup><a href="https://app.macroscope.com">Macroscope</a> summarized a83379d.</sup>
> <!-- Macroscope's review summary ends here -->
>
<!-- Macroscope's pull request summary ends here -->
