Keep a subagent's words in its own transcript, and count the ones already running
Two corrections to the previous commit. A subagent's closing report belongs in the subagent's transcript, which is where it already is; drawing it as a card in the parent's put the same paragraph in two places for a reader who did not ask for it. The row is a divider now -- a boundary, which is what the transcript actually needed there -- closed, saying only what reported and how it went. Opening it shows the report anyway, since leaving the conversation to read one line has its own cost, and a backgrounded command has no transcript of its own so this is the only place its report exists at all: that one names itself from its summary and has nothing left to open. `TranscriptDivider` grew a `trailing` slot for the chevron rather than the row growing its own copy of the rules. And the status was wrong for a session that was already running before the update, which is every session when the backend is replaced under it. Adoption picks a session's stdout back up from a recorded offset, so the `task_started` lines for subagents launched earlier are behind it and the translator never saw them -- it started with an empty set and reported `idle` with a subagent plainly still working. `Subagents::any_open` reads the directory instead, which is a measurement rather than bookkeeping and is right for a session this process did not start. Both sources are kept and neither subsumes the other: the translator's own set is the only thing that knows about a backgrounded *command*, which has no subagent to be found. The same pair decides whether an ending has already been reported, so a task that began before the restart still gets its divider. Echo's helpers now record their report as their own subagent's closing text, the way the real driver does, so the fixture has the shape being tested. Verified on the emulator: three dividers closed, one opened to its report, and each reply drawn as its own message. 170 server tests, ktfmt, clippy, rustfmt, Android lint and the JVM unit tests all clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5711c2568a
commit
ef1aad8776
11 files changed
+342
-120
No files matched your search
+13
-10
@@ -81,19 +81,22 @@ transcript is still being written to and its process is the session's to stop.
|
||||
`Waiting`, so the end-of-turn status `dispatch` produces for an ordinary
|
||||
session is dropped rather than written.
|
||||
|
||||
**The ending is also reported to the parent** (2026-09-06), as
|
||||
`Event::TaskNote { about, title, status, summary }`: the notification is a
|
||||
message the session received, and the turn it wakes up and runs would
|
||||
otherwise begin with nothing in front of it -- which drew two replies as
|
||||
one paragraph. Reported once however many of the two lifecycle shapes
|
||||
arrive; the `task_id -> tool_use_id` entry is removed as it is reported,
|
||||
which is what says the first one got there. See PLAN.md's "A task
|
||||
**The ending is also marked in the parent** (2026-09-06), as
|
||||
`Event::TaskNote { about, title, status, summary }`: the turn the session
|
||||
wakes up and runs would otherwise begin with nothing in front of it, which
|
||||
drew two replies as one paragraph. It is a **divider**, closed, and does
|
||||
not repeat the summary -- that is this subagent's own closing text, and
|
||||
here is not where somebody reads it. Reported once however many of the two
|
||||
lifecycle shapes arrive: whichever gets there first is the one that finds
|
||||
the task still open, and `finish` below closes it. See PLAN.md's "A task
|
||||
reporting back".
|
||||
|
||||
**While any task is outstanding the session's turn ends in
|
||||
`Status Waiting` rather than `Idle`** -- the same `tasks` map, asked
|
||||
whether it is empty. `Idle` means "waiting for a person", and a session
|
||||
with a backgrounded subagent is not doing that.
|
||||
`Status Waiting` rather than `Idle`.** `Idle` means "waiting for a person",
|
||||
and a session with a backgrounded subagent is not doing that. Two sources:
|
||||
the translator's `open_tasks`, and `Subagents::any_open` -- which is what
|
||||
covers a subagent launched before a backend restart adopted the session,
|
||||
whose `task_started` is behind the offset its stdout is read from.
|
||||
|
||||
**A limit the account hits inside a subagent is hoisted to the session**
|
||||
as well as recorded here, because `resume.rs` can only schedule against a
|
||||
|
||||
Reference in new issue
Block a user