From a76af598e98067f56f0ea2d2681b5c5df9dc3f57 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Fri, 16 Oct 2026 11:28:48 -0700 Subject: [PATCH] new summary after merge --- docs/operations.md | 2 +- internal/agents/manager.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/operations.md b/docs/operations.md index bf16cfa..6172b9a 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -150,7 +150,7 @@ Every session gets byre's guidance (`guidance` in `internal/agents/guidance.go`) A turn whose final message asks the human something in prose is bounced once (`takeBounce` in `internal/agents/guidance.go`): if `ask_human` wasn't called during the turn and the final message has a sentence ending in `?` outside code spans, code blocks, quotes and blockquotes, the agent is told to ask through `ask_human` and carries on. For Claude this is a Stop hook (`bounceProseQuestion`) that blocks the stop; Claude Code reports the block as a "Stop hook error" notification, which is expected. For Codex, byre doesn't end its turn on `turn/completed`: it records the nudge as a `byre` `user.message` with `mid_turn: true` and starts another Codex turn with it, and only that turn's end ends byre's turn. The per-turn flags reset when the next user message is sent. An agent told explicitly to ask in plain text will refuse the bounce. -A turn's final message is its summary, and it lives only in the transcript: nothing is filed in the inbox, so the human reads it once. When a task turn ends normally (not an error, not interrupted, not a handoff) with non-empty `result` text and didn't call `ask_human`, its `turn.ended` event carries `summary: true`. That flag drives the lead's "finished a turn" signal and the "Turn summaries" notification (see "Lead agent" and "Notifications"). A turn that asked a question has no summary, since the final message comes after the question it explains; the guidance tells agents to put everything the human needs in the question's context. There is no report tool: models write a closing recap whatever they are told, so byre uses it rather than asking for a second one. +A turn's final message is its summary, and it lives only in the transcript: nothing is filed in the inbox, so the human reads it once. When a task turn ends normally (not an error, not interrupted, not a handoff) with non-empty `result` text, didn't call `ask_human`, and isn't a Merge turn or discard turn (the task closes right after one, so its final message is never left to read), its `turn.ended` event carries `summary: true`. A Merge turn that called `stop_merge` keeps the task open and does carry it. That flag drives the lead's "finished a turn" signal and the "Turn summaries" notification (see "Lead agent" and "Notifications"). A turn that asked a question has no summary, since the final message comes after the question it explains; the guidance tells agents to put everything the human needs in the question's context. There is no report tool: models write a closing recap whatever they are told, so byre uses it rather than asking for a second one. Every turn starts as soon as it is sent; byre doesn't cap how many run at once. Whether a turn resumes the Claude conversation is decided by whether the session has ever sent one. diff --git a/internal/agents/manager.go b/internal/agents/manager.go index 83fa31f..19e3f56 100644 --- a/internal/agents/manager.go +++ b/internal/agents/manager.go @@ -842,12 +842,6 @@ func (m *Manager) turnEnded(ctx context.Context, l *live, res endResult) error { if sha != "" { payload["commit"] = sha } - switch { - case handoff: - payload["handoff"] = true - case finished && !compacting && !asked: - payload["summary"] = true - } discard, err := m.store.GetDiscard(ctx, l.taskID) if err != nil { return err @@ -861,6 +855,12 @@ func (m *Manager) turnEnded(ctx context.Context, l *live, res endResult) error { } snapshot := discard.State == store.DiscardNone review := snapshot && mergingBy == "" + switch { + case handoff: + payload["handoff"] = true + case finished && !compacting && !asked && review: + payload["summary"] = true + } go m.closeMergedSubtasks(l.taskID, l.dir) if payload["summary"] == true && snapshot { go m.reportToParent(l.taskID, res.result)