Take subagent reports out of the main transcript, and separate turns with a rule
A row per finished background task is a screenful of dividers about work the reader was not asking after, and one of them turned out to be a whole shell command drawn as centred prose, because its words came from somewhere with no reason to keep them short. `Event::TaskNote` is gone entirely, along with the row that drew it. A subagent's closing report is recorded as that subagent's own transcript's closing text and is read in the subcard, which is where it was already going; what the parent gets a row for is a message a subagent genuinely sends it, which arrives by the peer path and has had one all along. What remains is the actual defect and the smallest thing that fixes it. The fold still refuses to grow a settled reply, so a turn boundary is always a message boundary, and where two replies then abut it puts a `TurnBreak` between them: a hairline, no words, no colour. Made by the fold rather than sent by the server, because it is not something that happened -- it is the boundary between two things that did. `joinPages` puts one in at a page seam, which the fold never gets to see. The task notification is still what closes a task in `Status::Waiting`'s bookkeeping, and the registry lookup that recognises one this translator never saw start is what makes that work for a session adopted across a restart. Verified on the emulator: three replies, three rules, and nothing about the helpers anywhere in the parent. 170 server tests, 85 JVM tests, ktfmt, clippy, rustfmt and Android lint clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ef1aad8776
commit
1bbb642973
13 files changed
+171
-407
No files matched your search
+12
-10
@@ -81,22 +81,24 @@ 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 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".
|
||||
**The ending reaches the parent's transcript as nothing at all**
|
||||
(2026-09-06). It was tried, and a row per finished subagent is a screenful
|
||||
of dividers about work the reader was not asking after; the closing report
|
||||
is *this* transcript's last line and here is where somebody reads it. What
|
||||
the parent gets a row for is a message a subagent genuinely sends it, which
|
||||
arrives by the peer path. The two lifecycle shapes are still handled once:
|
||||
whichever gets there first is the one that finds the task still open, and
|
||||
`finish` below closes it. See PLAN.md's "Two turns must never be drawn as
|
||||
one".
|
||||
|
||||
**While any task is outstanding the session's turn ends in
|
||||
`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.
|
||||
whose `task_started` is behind the offset its stdout is read from. That
|
||||
second lookup is also what lets such a subagent's ending be recognised at
|
||||
all.
|
||||
|
||||
**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