Draw a background task as what it ran, and go there on a tap

A card in the session's panel said "background command" under every
description -- and for Codex, which names a terminal by a process id and
gives no description at all, that phrase was the whole of every card.

Both halves of the answer are in the transcript rather than in what the
provider says: a driver now reports which tool call its task belongs to
(Claude's `task_started` carries the `tool_use_id`, Codex's terminal list
the `itemId`), and `LiveSession::background_tasks` resolves those ids
against the transcript into a sequence number and, where the provider said
nothing, the command the call was made with. So the card draws the command,
and the kind shrinks to a mark beside it whose name is what a screen reader
is given.

Tapping one goes to that call in the transcript, opened, which is where a
backgrounded command's output already lands -- rather than drawing a second
copy of it beside the panel. The journey is the one a reopened session
already makes to put a reader back where they stopped, now one function
(`travelTo`). It has to release the held backlog first: events arriving
while the reader is away from the newest end are held rather than applied,
so a task started since they scrolled back was in no row at all and the tap
looked like it had done nothing.

Verified against the sandbox on the emulator: the panel draws
`sleep 120 && echo done` for an echo session's `/background`, and tapping
it lands on that Bash card with its output showing.
This commit is contained in:
iris-ai committed 2026-09-20 18:46:22 -04:00
1 parent 3b309766d7
commit cedb18e8c1
18 files changed
+635 -151

No files matched your search

+33 -5
View File
@@ -1156,15 +1156,43 @@ written to a transcript and never kept here, because it is a measurement of a
running process and a session with none has nothing to report -- that route
answers `null` for one, which the panel says in words rather than drawing as an
empty list. Each entry is an id the reader never sees, the provider's own
description, and a kind; `description` is optional because Codex names a
background terminal by a process id, and a card with nothing to say says the
kind instead of dressing the number up as a name. The section is collapsed to
description, a kind, and where the call that started it is. The section is
collapsed to
its one-line count by default and pushes the subagents down when opened, and it
is refetched whenever the live `backgroundTasks` count moves, since a card for
work that has finished is exactly the stale measurement the count was designed
not to be. A backgrounded subagent appears in both lists: the background one
because it is running, the subagent one because it has a transcript -- and only
the subagent card opens, because only it has anything to open.
because it is running, the subagent one because it has a transcript -- and the
two cards lead to different places, the subagent's to its own transcript and the
background one's to the call in *this* transcript that started it.
**A card says what was run, and tapping it goes to where it was run**
(2026-09-20). The first version drew the kind as a second line under the
description, which on a panel of backgrounded commands was "background command"
repeated down the list -- and Codex, which names a terminal by a process id and
gives no description at all, drew that phrase as the *whole* of every card. Both
halves of the answer come from the transcript rather than from the provider: a
driver reports the tool call its task belongs to (Claude's `task_started`
carries the `tool_use_id` beside the `task_id`; Codex's terminal list carries
the `itemId`), and `Session::background_tasks` resolves those ids against the
transcript into a sequence number and, where the provider said nothing, the
command the call was made with. So the panel draws the command, and the kind
shrinks to a mark beside it whose name is what a screen reader is given.
What tapping does is **go to the call**, opened, rather than show the output
beside the panel. The output is already in that card -- a backgrounded command's
report replaces the launch result there, above -- so a second copy would be a
second version of the same truth, and the card in its place also says what the
session was doing when it started. The journey is the one a reopened session
already makes to put a reader back where they stopped, which is why it is one
function (`travelTo`): page history back until the row is loaded, open the call
and the run it is drawn in, then scroll, with nothing drawn on the way. What a
jump has to do first and a restore never does is **release the held backlog**:
events arriving while the reader is away from the newest end are held rather
than applied, so a task started since they scrolled back is in no row at all --
found by testing it, where the tap looked like it had done nothing. A task
whose call the transcript does not hold -- an adopted process whose start was
never seen -- has no chevron and does not invite the tap.
**An `ambient` task is not background work.** The same level signal carries
live-update watchers and housekeeping marked `ambient`, which the CLI says