Commit and snapshot in ask_human before suggesting a main merge
This commit is contained in:
+1
-1
@@ -1620,7 +1620,7 @@ components:
|
||||
type: string
|
||||
enum: [message, turn_end, tool_call, ask_human, timer, requested, answer, fork]
|
||||
x-enum-varnames: [SnapshotTriggerMessage, SnapshotTriggerTurnEnd, SnapshotTriggerToolCall, SnapshotTriggerAskHuman, SnapshotTriggerTimer, SnapshotTriggerRequested, SnapshotTriggerAnswer, SnapshotTriggerFork]
|
||||
description: "turn_end: after byre's end-of-turn commit. requested: a task's agent or the lead asked for it with take_snapshot. answer: just before answers from the human were handed to the agent. fork: when the task's agent forked the task with its fork tool. answer and fork snapshots are never reviewed. message (the agent wrote text after one or more tool calls), tool_call, ask_human and timer appear only on snapshots taken by earlier builds."
|
||||
description: "turn_end: after byre's end-of-turn commit. requested: a task's agent or the lead asked for it with take_snapshot. answer: just before answers from the human were handed to the agent. fork: when the task's agent forked the task with its fork tool. ask_human: after byre committed the worktree inside an ask_human call whose task is behind the default branch, just before suggesting the agent merge it in. answer, fork and ask_human snapshots are never reviewed. message (the agent wrote text after one or more tool calls), tool_call and timer appear only on snapshots taken by earlier builds."
|
||||
created_at: { type: string, format: date-time }
|
||||
|
||||
Preview:
|
||||
|
||||
+5
-5
@@ -37,11 +37,11 @@ A task ends `merged` or `discarded`; either way its sessions are stopped, its sn
|
||||
|
||||
A task's summary is what its agent writes, before the task closes, about the whole task: what it set out to do, what was built or tried, the key decisions and why, and what was left out. The agent sets it with the `set_task_summary` MCP tool (`internal/agents/summary.go`), any time while the task is active; each call replaces `tasks.summary` and records a `task.summary` event carrying it, which the transcript shows as a note. The Merge turn's prompt and the discard turn's prompt (`summaryRequest`) both ask for it. Turn summaries don't stand in for it: each covers only its own turn, and a merged task's last one is always the Merge turn's. Tasks closed before the column existed have none. `sqlite3 byre.db "SELECT id, status, summary FROM tasks WHERE status != 'active' ORDER BY closed_at DESC LIMIT 5"` shows recent ones.
|
||||
|
||||
An implementer says its task is ready to merge with the `ready_for_merge` MCP tool (`internal/agents/ready.go`), whose `overview` covers the whole task for a human switching between tasks: a summary, tradeoffs and compromises, what was not done, and future TODOs. Its description tells the agent to call it only once the review of its most recent changes has come back, never in the same turn as a change or while that review is pending. Each call records a `task.ready` event carrying it, which the lead gets as a signal and the transcript draws as a bubble (`ReadyBubble` in `mac/Sources/Byre/Chat.swift`) headed "ready for merge". The latest one, while the task is active and no question, `task.ready_cleared` or snapshot other than an answer snapshot has come since it (a question, a withdrawal or dismissal, or newer work the overview doesn't cover), is drawn like an open question (the warn tint and border) and carries small Dismiss, Merge and Discard buttons that act like the header's, confirmation dialogs included; earlier ones are drawn like an answered question (the faint warn tint), without buttons. Recording it changes nothing else. byre asks for it (`readyPrompt`, sent as a byre message) when a task's state goes to `idle`, `ready_to_merge` or `discard_suggested` (`readyState`) or its workflow finishes (`Manager.Observe` calls `promptReady`) and the latest non-answer snapshot's review is `done` or `skipped`. It checks and sends under the session's delivery lock (the one human messages and answers take), and only to an agent that isn't running, so the prompt never queues behind a turn that could add unreviewed work. `tasks.ready_prompt_seq` holds the task's last event seq when the prompt's turn started; byre asks again only once a non-answer snapshot or a message from the human (a chat message or a question's answer, not one from byre, the agent or the lead) has come after it, so the agent's own turns that change no files don't ask again, and a human unblocking an agent that said it was waiting does. It doesn't ask while the task has an open question. It doesn't ask for a workflow stage task until its run has a `task.workflow_finished` event (by then the run's other stage tasks are being discarded, leaving the final one for the human), a task in any other state (an open question, a held merge or a merge after review among them), or a review that failed, and it skips the `reviewing` → `idle` change of a review with findings, since those go to the agent; the turn that answers them asks once it ends without new work. The prompt tells the agent not to call the tool, and to say what's left, when the task isn't ready. When that review is `skipped` (the snapshot has no diff from the default branch), byre sends `readyPromptUnchanged` instead, which says there is nothing to merge and offers only `suggest_discard` and `ask_human`.
|
||||
An implementer says its task is ready to merge with the `ready_for_merge` MCP tool (`internal/agents/ready.go`), whose `overview` covers the whole task for a human switching between tasks: a summary, tradeoffs and compromises, what was not done, and future TODOs. Its description tells the agent to call it only once the review of its most recent changes has come back, never in the same turn as a change or while that review is pending. Each call records a `task.ready` event carrying it, which the lead gets as a signal and the transcript draws as a bubble (`ReadyBubble` in `mac/Sources/Byre/Chat.swift`) headed "ready for merge". The latest one, while the task is active and no question, `task.ready_cleared` or snapshot other than an `answer`, `fork` or `ask_human` one (the never-reviewed kinds) has come since it (a question, a withdrawal or dismissal, or newer work the overview doesn't cover), is drawn like an open question (the warn tint and border) and carries small Dismiss, Merge and Discard buttons that act like the header's, confirmation dialogs included; earlier ones are drawn like an answered question (the faint warn tint), without buttons. Recording it changes nothing else. byre asks for it (`readyPrompt`, sent as a byre message) when a task's state goes to `idle`, `ready_to_merge` or `discard_suggested` (`readyState`) or its workflow finishes (`Manager.Observe` calls `promptReady`) and the latest reviewable snapshot's review is `done` or `skipped`. It checks and sends under the session's delivery lock (the one human messages and answers take), and only to an agent that isn't running, so the prompt never queues behind a turn that could add unreviewed work. `tasks.ready_prompt_seq` holds the task's last event seq when the prompt's turn started; byre asks again only once a reviewable snapshot or a message from the human (a chat message or a question's answer, not one from byre, the agent or the lead) has come after it, so the agent's own turns that change no files don't ask again, and a human unblocking an agent that said it was waiting does. It doesn't ask while the task has an open question. It doesn't ask for a workflow stage task until its run has a `task.workflow_finished` event (by then the run's other stage tasks are being discarded, leaving the final one for the human), a task in any other state (an open question, a held merge or a merge after review among them), or a review that failed, and it skips the `reviewing` → `idle` change of a review with findings, since those go to the agent; the turn that answers them asks once it ends without new work. The prompt tells the agent not to call the tool, and to say what's left, when the task isn't ready. When that review is `skipped` (the snapshot has no diff from the default branch), byre sends `readyPromptUnchanged` instead, which says there is nothing to merge and offers only `suggest_discard` and `ask_human`.
|
||||
|
||||
An implementer that thinks its task shouldn't land at all (the approach failed, the task turned out unnecessary or already done) says so with the `suggest_discard` MCP tool (also `internal/agents/ready.go`), whose `reason` explains why; `readyPrompt` offers it as the alternative to `ready_for_merge`. Each call records a `task.discard_suggested` event, which the lead gets as a signal and the transcript draws with the same `ReadyBubble`, headed "suggests discarding". It takes part in "latest" with the ready-for-merge overviews, so whichever of the two came last is the current one, drawn and cleared under the same rules, and it carries only the Discard button. It only suggests: the task stays open until the human discards it.
|
||||
|
||||
`tasks.ready` is `merge` or `discard` after the latest of these two calls, set in the same transaction as its event, and is cleared by the same things that clear the latest bubble: a snapshot other than an answer snapshot, a new inbox item, or a `task.ready_cleared` event. That event comes from the agent's `cancel_ready` MCP tool (also `internal/agents/ready.go`, for when its call no longer holds) or from `DELETE /api/tasks/{taskId}/ready`, which the current bubble's small Dismiss button sends; the lead gets it as a signal and the transcript draws it as a note. It feeds the task's state (`ready_to_merge` or `discard_suggested`, see "Task state in the store"), which the switcher's and the Project tab's task rows show as **Ready to merge** or **Ready to discard**, in the warn colour with a warn dot like **Needs your answer**. The app reloads a project's tasks on `task.ready`, `task.discard_suggested`, `task.ready_cleared`, `snapshot.created` and `task.state`.
|
||||
`tasks.ready` is `merge` or `discard` after the latest of these two calls, set in the same transaction as its event, and is cleared by the same things that clear the latest bubble: a snapshot other than an `answer`, `fork` or `ask_human` one, a new inbox item, or a `task.ready_cleared` event. That event comes from the agent's `cancel_ready` MCP tool (also `internal/agents/ready.go`, for when its call no longer holds) or from `DELETE /api/tasks/{taskId}/ready`, which the current bubble's small Dismiss button sends; the lead gets it as a signal and the transcript draws it as a note. It feeds the task's state (`ready_to_merge` or `discard_suggested`, see "Task state in the store"), which the switcher's and the Project tab's task rows show as **Ready to merge** or **Ready to discard**, in the warn colour with a warn dot like **Needs your answer**. The app reloads a project's tasks on `task.ready`, `task.discard_suggested`, `task.ready_cleared`, `snapshot.created` and `task.state`.
|
||||
|
||||
Agents find closed tasks with the `search_closed_tasks` MCP tool, which task agents get for their own project and the lead for one project (`project_id`) or all: a case-insensitive substring match of `query` on title, merge title, TODO item, summary and merge commit (`Store.SearchClosedTasks`), newest closed first, at most `limit` (default 20, at most 100), each with its id, outcome, merge commit, close time, creator, titles, TODO item, fork source and summary. The lead reads a closed task's transcript with `read_transcript`. There is no closed-task list in the UI; the human asks the lead.
|
||||
|
||||
@@ -319,7 +319,7 @@ The **Project** tab is the dashboard of the right pane's project (the focused ta
|
||||
|
||||
## Inbox
|
||||
|
||||
Agents ask questions with the `ask_human` MCP tool. Each question carries a `context` with the background the human needs to answer without reading the transcript, and its choices are written inline in that context as Markdown list items: `- ( ) text` for pick-one choices, with exactly one `- (*) text` marking the recommendation, or `- [ ] text` for pick-any choices, with `- [x] text` marking the recommended ones. There is no separate list of options. byre parses the choices out of `context` (`internal/agents/choices.go`; list items inside code fences and blockquotes don't count) and stores their text in the payload as `options`, with `multiple` (pick-any) and `recommended`. The UI renders the context as Markdown with a radio button or checkbox in place of each choice's marker. The tool's description tells agents to keep everything about one choice (what it does, its example, code, trade-offs) in lines indented beneath that choice rather than in text above the list; those lines render inside the option, and only the marker line's text is the option. When every item of a choice list has exactly one non-blank indented line and that line is only a Markdown image, the list renders as a grid of tiles (`grid`, set in `parseList` in `mac/Sources/Byre/Markdown.swift`): four across, or two across when the context is at most 480pt wide. The tool's description tells agents to write image choices this way. A malformed call (no `context` or `why_blocked`, fewer than two choices, pick-one and pick-any choices mixed, a pick-one question without exactly one recommendation, two choices with the same text, an unknown attachment kind, a foreign `thread_id`) is rejected with a message saying what to fix, and nothing is filed. All questions are alike: the tool's description and its result tell the agent to end its turn after asking, and the answer arrives as its next message. When the task's worktree is behind the default branch (`git.Behind`: commits on the repo's local default branch that `HEAD` lacks), the result says by how many, and suggests merging it in while the human answers before ending the turn. The call returns the item's id as `question_id`. An agent withdraws a question it no longer needs answered (the human answered it in a chat message, say) with the `cancel_question` MCP tool and that id: an `open` question of its own session becomes `dismissed` with no `resolved_by` (its `inbox.updated` event has actor `agent`), which also stops it from holding back delivery; anything else is rejected with a message saying why. The inbox holds only questions; errors go in the transcript (see "Errors").
|
||||
Agents ask questions with the `ask_human` MCP tool. Each question carries a `context` with the background the human needs to answer without reading the transcript, and its choices are written inline in that context as Markdown list items: `- ( ) text` for pick-one choices, with exactly one `- (*) text` marking the recommendation, or `- [ ] text` for pick-any choices, with `- [x] text` marking the recommended ones. There is no separate list of options. byre parses the choices out of `context` (`internal/agents/choices.go`; list items inside code fences and blockquotes don't count) and stores their text in the payload as `options`, with `multiple` (pick-any) and `recommended`. The UI renders the context as Markdown with a radio button or checkbox in place of each choice's marker. The tool's description tells agents to keep everything about one choice (what it does, its example, code, trade-offs) in lines indented beneath that choice rather than in text above the list; those lines render inside the option, and only the marker line's text is the option. When every item of a choice list has exactly one non-blank indented line and that line is only a Markdown image, the list renders as a grid of tiles (`grid`, set in `parseList` in `mac/Sources/Byre/Markdown.swift`): four across, or two across when the context is at most 480pt wide. The tool's description tells agents to write image choices this way. A malformed call (no `context` or `why_blocked`, fewer than two choices, pick-one and pick-any choices mixed, a pick-one question without exactly one recommendation, two choices with the same text, an unknown attachment kind, a foreign `thread_id`) is rejected with a message saying what to fix, and nothing is filed. All questions are alike: the tool's description and its result tell the agent to end its turn after asking, and the answer arrives as its next message. When the task's worktree is behind the default branch (`git.Behind`: commits on the repo's local default branch that `HEAD` lacks) and the turn isn't a Merge or Sync turn that owns the worktree's merge, byre first commits the worktree itself (`commitBeforeSync`: `git.CommitAll` under the task's mutex) and takes an `ask_human` snapshot of it, so the agent never commits on its own and there is a forkable point just before the merge. The result then says how many commits behind it is and suggests merging the default branch in while the human answers: `git merge --no-ff --no-commit`, resolve, check, and leave it uncommitted for byre's end-of-turn commit to conclude, as **Sync from main** does, then end the turn. When the commit or snapshot fails, it is logged as `commit before merging default branch` and recorded as a `session.error`, and the result just says to end the turn. The call returns the item's id as `question_id`. An agent withdraws a question it no longer needs answered (the human answered it in a chat message, say) with the `cancel_question` MCP tool and that id: an `open` question of its own session becomes `dismissed` with no `resolved_by` (its `inbox.updated` event has actor `agent`), which also stops it from holding back delivery; anything else is rejected with a message saying why. The inbox holds only questions; errors go in the transcript (see "Errors").
|
||||
|
||||
`GET /api/inbox` is one query over open items, oldest first; `project_id` and `task_id` narrow it to a project or task view, and `state` picks another state. The right pane shows a task's questions in its transcript, where they were asked, and they are answered there (below).
|
||||
|
||||
@@ -336,7 +336,7 @@ An `other` response, or a pick-any `option` one, may carry `images`, blob ids fr
|
||||
|
||||
A submission is all or nothing. `Store.Respond` resolves each item with an `UPDATE` conditioned on `state = 'open'` in one transaction, so when any item was answered, dismissed or withdrawn by someone else in the meantime (a second tab, the lead's `answer_question`, the agent's `cancel_question`), the whole submission is rolled back and refused with 409, and no response is recorded.
|
||||
|
||||
Answers reach the agent as one message holding every undelivered `option` and `other` response of the session (`deliveryMessage` in `internal/agents/inbox.go`), never while one of its questions is still open and unanswered (`AwaitingHuman` in `internal/store/inbox.go`); until then they stay held (`inbox_responses.delivered_at` empty). While a turn is running, the task session's PostToolUse hook (`afterTool` in `internal/agents/snapshots.go`, through `deliverMidTurn`) hands them over after the agent's next tool call as the hook's `additionalContext`, after any queued messages (see "Agent sessions"), so the agent reads them alongside that tool's result without being interrupted (for Antigravity, the `PreInvocation` hook hands them over as a user message before the model's next call after the first; for Codex, after each completed tool item, `deliverMidTurn` hands them over with `turn/steer` instead; when the steer fails, `restoreMidTurn` puts the taken queued messages back under their original ids and clears the answers' `delivered_at` and `snapshot_n`, so `Deliver` sends them when the turn ends, and logs `mid-turn delivery restored`); the `user.message` event recording it carries `mid_turn: true` and no `head`, and the transcript doesn't treat it as a turn start. A turn that makes no further tool call leaves them to `Deliver`, which runs after each submission and when a turn ends, and sends them as a new turn once the session is `idle`. Just before either hands answers over, byre snapshots the task's worktree (`snapshotForAnswer` in `internal/agents/snapshots.go`, trigger `answer`), synchronously and under the task's mutex, and records the snapshot's `n` on each answer it hands over (`inbox_responses.snapshot_n`, `snapshot_n` in the API), so the snapshot's tree and `event_seq` give the worktree and the conversation as they stood before the agent read the answer. A new snapshot is taken for every hand-over, even when the tree is unchanged, so each one's `event_seq` and session are the conversation boundary just before that answer and `POST /api/tasks/{taskId}/snapshots/{n}/fork` on it continues from there. An `answer` snapshot is never reviewed, nor is a `fork` one (see "Forking"). Everything that looks for the task's latest snapshot to judge review state skips both (`LastReviewable`): the dedupe of the other triggers, which skip a snapshot only when its tree equals the last non-`answer` one's, so work an `answer` snapshot caught mid-turn is still snapshotted and reviewed when the turn ends; Merge after review; and the Merge confirmation's review warnings. A Merge turn already holds the task's mutex, so mid-turn delivery in it snapshots without taking it again; a worktree with merge conflicts snapshots with the conflict markers as they stand, and its real index is left untouched. No snapshot is taken once the task is closing, or when taking it fails; the answers then have no `snapshot_n`. A failure is logged as `take snapshot` and recorded as a `session.error` in the transcript, and the answers are still handed over: holding them would leave an idle agent waiting with nothing to retry the delivery. The log traces each answer: `inbox response recorded` when it is stored, `deliver held` with the reason, `deliver sent mid-turn` with the snapshot, `deliver sent` with the session's state, the snapshot and whether its agent process had exited or byre was closing, and `undelivered responses` with a reason wherever a session has held answers when its turn ends in a handoff or merge, its agent process ends, startup resumes it, or startup finds it idle. `sqlite3 byre.db "SELECT * FROM inbox_responses WHERE delivered_at IS NULL"` lists the answers held now.
|
||||
Answers reach the agent as one message holding every undelivered `option` and `other` response of the session (`deliveryMessage` in `internal/agents/inbox.go`), never while one of its questions is still open and unanswered (`AwaitingHuman` in `internal/store/inbox.go`); until then they stay held (`inbox_responses.delivered_at` empty). While a turn is running, the task session's PostToolUse hook (`afterTool` in `internal/agents/snapshots.go`, through `deliverMidTurn`) hands them over after the agent's next tool call as the hook's `additionalContext`, after any queued messages (see "Agent sessions"), so the agent reads them alongside that tool's result without being interrupted (for Antigravity, the `PreInvocation` hook hands them over as a user message before the model's next call after the first; for Codex, after each completed tool item, `deliverMidTurn` hands them over with `turn/steer` instead; when the steer fails, `restoreMidTurn` puts the taken queued messages back under their original ids and clears the answers' `delivered_at` and `snapshot_n`, so `Deliver` sends them when the turn ends, and logs `mid-turn delivery restored`); the `user.message` event recording it carries `mid_turn: true` and no `head`, and the transcript doesn't treat it as a turn start. A turn that makes no further tool call leaves them to `Deliver`, which runs after each submission and when a turn ends, and sends them as a new turn once the session is `idle`. Just before either hands answers over, byre snapshots the task's worktree (`snapshotForAnswer` in `internal/agents/snapshots.go`, trigger `answer`), synchronously and under the task's mutex, and records the snapshot's `n` on each answer it hands over (`inbox_responses.snapshot_n`, `snapshot_n` in the API), so the snapshot's tree and `event_seq` give the worktree and the conversation as they stood before the agent read the answer. A new snapshot is taken for every hand-over, even when the tree is unchanged, so each one's `event_seq` and session are the conversation boundary just before that answer and `POST /api/tasks/{taskId}/snapshots/{n}/fork` on it continues from there. An `answer` snapshot is never reviewed, nor is a `fork` one (see "Forking") or an `ask_human` one (above). Everything that looks for the task's latest snapshot to judge review state skips all three (`LastReviewable`): the dedupe of the other triggers, which skip a snapshot only when its tree equals the last non-`answer` one's, so work an `answer` snapshot caught mid-turn is still snapshotted and reviewed when the turn ends; Merge after review; and the Merge confirmation's review warnings. A Merge turn already holds the task's mutex, so mid-turn delivery in it snapshots without taking it again; a worktree with merge conflicts snapshots with the conflict markers as they stand, and its real index is left untouched. No snapshot is taken once the task is closing, or when taking it fails; the answers then have no `snapshot_n`. A failure is logged as `take snapshot` and recorded as a `session.error` in the transcript, and the answers are still handed over: holding them would leave an idle agent waiting with nothing to retry the delivery. The log traces each answer: `inbox response recorded` when it is stored, `deliver held` with the reason, `deliver sent mid-turn` with the snapshot, `deliver sent` with the session's state, the snapshot and whether its agent process had exited or byre was closing, and `undelivered responses` with a reason wherever a session has held answers when its turn ends in a handoff or merge, its agent process ends, startup resumes it, or startup finds it idle. `sqlite3 byre.db "SELECT * FROM inbox_responses WHERE delivered_at IS NULL"` lists the answers held now.
|
||||
|
||||
### Errors
|
||||
|
||||
@@ -433,7 +433,7 @@ The **Terminal** tab (`mac/Sources/Byre/Terminal.swift`) draws it with SwiftTerm
|
||||
|
||||
byre snapshots each task's worktree at the end of every turn that has no subagents running (`internal/agents/snapshots.go`, `internal/git/snapshot.go`), so a snapshot always sits on a turn boundary, the only place a Codex conversation can be forked. A snapshot builds the tree the same way as the Changes view (a copy of the real index, `git add --all`, `git write-tree`), commits it with `git commit-tree` whose parent is the worktree's `HEAD`, authored as the session's creator with the message `byre snapshot <n> (<trigger>)`, and points `refs/byre/tasks/<task-id>/snap/<n>` at it (`git update-ref` with an empty old value, so an existing ref is never overwritten). A row in the `snapshots` table records id, task, session, `n` (from 1 per task), commit and tree shas, `event_seq` (the task's latest event when the snapshot started, at or after the turn's `turn.ended`, so the tree holds at least the work up to that event), the trigger and the time, and the same transaction records a `snapshot.created` event carrying the row.
|
||||
|
||||
The trigger is `turn_end`: the snapshot starts after byre's end-of-turn commit and the `turn.ended` event. A turn that ends while the session's subagent count (see "Subagent count") is above zero takes no snapshot and requests no review, since its work is half done; the CLI starts another turn when each background subagent finishes, and the first of those to end with none running takes the snapshot and its review. An interrupted turn likewise takes no snapshot and requests no review, so the next turn to end uninterrupted snapshots its work and has it reviewed even when that turn changed no files. The trigger `answer` is a snapshot taken just before answers from the human are handed to the agent (see "Inbox"); it is taken even when its tree is unchanged, is never reviewed (its transcript row has no review button), and doesn't wait in the queue below but runs at once under the task's mutex. Snapshots taken by earlier builds also carry `message` (mid-turn, when the agent wrote text after tool calls), `tool_call`, `ask_human` and `timer`. A snapshot whose tree equals the task's latest snapshot's tree is skipped, so a turn that changed no files leaves none. Snapshots run one at a time per task: a trigger that arrives while one is running replaces any already waiting one, and the waiting one runs when the current one finishes. Failures are logged and dropped.
|
||||
The trigger is `turn_end`: the snapshot starts after byre's end-of-turn commit and the `turn.ended` event. A turn that ends while the session's subagent count (see "Subagent count") is above zero takes no snapshot and requests no review, since its work is half done; the CLI starts another turn when each background subagent finishes, and the first of those to end with none running takes the snapshot and its review. An interrupted turn likewise takes no snapshot and requests no review, so the next turn to end uninterrupted snapshots its work and has it reviewed even when that turn changed no files. The trigger `answer` is a snapshot taken just before answers from the human are handed to the agent (see "Inbox"); it is taken even when its tree is unchanged, is never reviewed (its transcript row has no review button), and doesn't wait in the queue below but runs at once under the task's mutex. The trigger `ask_human` is a snapshot taken the same way, inside an `ask_human` call, right after byre commits the worktree of a task that is behind the default branch (see "Inbox"); it is never reviewed either. Snapshots taken by earlier builds also carry `message` (mid-turn, when the agent wrote text after tool calls), `tool_call` and `timer`. A snapshot whose tree equals the task's latest snapshot's tree is skipped, so a turn that changed no files leaves none. Snapshots run one at a time per task: a trigger that arrives while one is running replaces any already waiting one, and the waiting one runs when the current one finishes. Failures are logged and dropped.
|
||||
|
||||
The `take_snapshot` MCP tool asks for a snapshot now (`RequestSnapshot` and `takeSnapshotTool` in `internal/agents/snapshots.go`): a task's agent calls it with no arguments for its own task, and the lead with a `task_id`. The snapshot has trigger `requested`, is taken even when its tree equals the latest snapshot's (so it retries a failed review of unchanged work), and is reviewed like any other (see "Reviews"); it counts as a review request (`BeginReviewRequest`) from the call until the reviewer starts. It is attributed to the task's latest implementer session, authored as that session's creator, and can be taken mid-turn, uncommitted work included. A requested snapshot that is replaced while waiting passes its trigger and its taken-even-when-unchanged to the one that replaces it. Refused for a closed task, while the task is merging or being discarded, and for a task with no agent session.
|
||||
|
||||
|
||||
@@ -175,12 +175,29 @@ func (m *Manager) ask(ctx context.Context, l *live, raw json.RawMessage) (string
|
||||
if err != nil {
|
||||
slog.Error("count commits behind default branch", "task", task.Id, "err", err)
|
||||
}
|
||||
if behind > 0 {
|
||||
return filed + fmt.Sprintf("This worktree is %d commits behind %s. While the human answers is a good time to merge %s in: "+
|
||||
"commit your work if the tree isn't clean, run `git merge %s`, resolve any conflicts, and check the result. Then end your turn. ",
|
||||
if behind == 0 || m.ownsTask(l.id) {
|
||||
return filed + "End your turn now. " + rest, nil
|
||||
}
|
||||
err = m.commitBeforeSync(ctx, l, project.DefaultBranch)
|
||||
if err != nil {
|
||||
slog.Error("commit before merging default branch", "task", task.Id, "err", err)
|
||||
m.recordError(l, fmt.Sprintf("byre couldn't commit and snapshot the worktree before suggesting a merge of %s: %v", project.DefaultBranch, err))
|
||||
return filed + "End your turn now. " + rest, nil
|
||||
}
|
||||
return filed + fmt.Sprintf("This worktree is %d commits behind %s, and byre has committed and snapshotted your work so far. While the human answers is a good time to merge %s in: "+
|
||||
"run `git merge --no-ff --no-commit %s`, resolve any conflicts, check the result, and leave the merge uncommitted; byre's end-of-turn commit concludes it. Then end your turn. ",
|
||||
behind, project.DefaultBranch, project.DefaultBranch, project.DefaultBranch) + rest, nil
|
||||
}
|
||||
return filed + "End your turn now. " + rest, nil
|
||||
|
||||
func (m *Manager) commitBeforeSync(ctx context.Context, l *live, branch string) error {
|
||||
unlock := m.lockTask(l.taskID)
|
||||
defer unlock()
|
||||
_, err := git.CommitAll(l.dir, "Work before merging "+branch, l.gitName, l.gitEmail)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = m.cutSnapshot(ctx, liveTarget(l), true, api.SnapshotTriggerAskHuman)
|
||||
return err
|
||||
}
|
||||
|
||||
type cancelArgs struct {
|
||||
|
||||
+192
-191
@@ -1198,11 +1198,11 @@ type Snapshot struct {
|
||||
TaskId string `json:"task_id"`
|
||||
TreeSha string `json:"tree_sha"`
|
||||
|
||||
// Trigger turn_end: after byre's end-of-turn commit. requested: a task's agent or the lead asked for it with take_snapshot. answer: just before answers from the human were handed to the agent. fork: when the task's agent forked the task with its fork tool. answer and fork snapshots are never reviewed. message (the agent wrote text after one or more tool calls), tool_call, ask_human and timer appear only on snapshots taken by earlier builds.
|
||||
// Trigger turn_end: after byre's end-of-turn commit. requested: a task's agent or the lead asked for it with take_snapshot. answer: just before answers from the human were handed to the agent. fork: when the task's agent forked the task with its fork tool. ask_human: after byre committed the worktree inside an ask_human call whose task is behind the default branch, just before suggesting the agent merge it in. answer, fork and ask_human snapshots are never reviewed. message (the agent wrote text after one or more tool calls), tool_call and timer appear only on snapshots taken by earlier builds.
|
||||
Trigger SnapshotTrigger `json:"trigger"`
|
||||
}
|
||||
|
||||
// SnapshotTrigger turn_end: after byre's end-of-turn commit. requested: a task's agent or the lead asked for it with take_snapshot. answer: just before answers from the human were handed to the agent. fork: when the task's agent forked the task with its fork tool. answer and fork snapshots are never reviewed. message (the agent wrote text after one or more tool calls), tool_call, ask_human and timer appear only on snapshots taken by earlier builds.
|
||||
// SnapshotTrigger turn_end: after byre's end-of-turn commit. requested: a task's agent or the lead asked for it with take_snapshot. answer: just before answers from the human were handed to the agent. fork: when the task's agent forked the task with its fork tool. ask_human: after byre committed the worktree inside an ask_human call whose task is behind the default branch, just before suggesting the agent merge it in. answer, fork and ask_human snapshots are never reviewed. message (the agent wrote text after one or more tool calls), tool_call and timer appear only on snapshots taken by earlier builds.
|
||||
type SnapshotTrigger string
|
||||
|
||||
// Stage defines model for Stage.
|
||||
@@ -4227,195 +4227,196 @@ var swaggerSpec = []string{
|
||||
"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",
|
||||
}
|
||||
|
||||
// decodeSpec returns the embedded OpenAPI spec as raw JSON bytes,
|
||||
|
||||
@@ -69,12 +69,12 @@ func (s *Store) LastSnapshot(ctx context.Context, taskID string) (api.Snapshot,
|
||||
}
|
||||
|
||||
func CutPoint(trigger api.SnapshotTrigger) bool {
|
||||
return trigger == api.SnapshotTriggerAnswer || trigger == api.SnapshotTriggerFork
|
||||
return trigger == api.SnapshotTriggerAnswer || trigger == api.SnapshotTriggerFork || trigger == api.SnapshotTriggerAskHuman
|
||||
}
|
||||
|
||||
func (s *Store) LastReviewable(ctx context.Context, taskID string) (api.Snapshot, error) {
|
||||
snap, err := scanSnapshot(s.db.QueryRowContext(ctx, `SELECT `+snapshotColumns+` FROM snapshots WHERE task_id = ? AND trigger NOT IN (?, ?) ORDER BY n DESC LIMIT 1`,
|
||||
taskID, string(api.SnapshotTriggerAnswer), string(api.SnapshotTriggerFork)))
|
||||
snap, err := scanSnapshot(s.db.QueryRowContext(ctx, `SELECT `+snapshotColumns+` FROM snapshots WHERE task_id = ? AND trigger NOT IN (?, ?, ?) ORDER BY n DESC LIMIT 1`,
|
||||
taskID, string(api.SnapshotTriggerAnswer), string(api.SnapshotTriggerFork), string(api.SnapshotTriggerAskHuman)))
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return snap, ErrNotFound
|
||||
}
|
||||
|
||||
@@ -766,9 +766,9 @@ func (s *Store) ReadyPromptDue(ctx context.Context, id string) (bool, error) {
|
||||
err := s.db.QueryRowContext(ctx, `SELECT EXISTS (
|
||||
SELECT 1 FROM events e, tasks t
|
||||
WHERE t.id = ? AND e.task_id = t.id AND e.seq > t.ready_prompt_seq
|
||||
AND ((e.kind = 'snapshot.created' AND json_extract(e.payload, '$.trigger') NOT IN (?, ?))
|
||||
AND ((e.kind = 'snapshot.created' AND json_extract(e.payload, '$.trigger') NOT IN (?, ?, ?))
|
||||
OR (e.kind = 'user.message' AND e.actor NOT IN ('byre', ?) AND e.actor NOT LIKE '% (lead)'))
|
||||
)`, id, string(api.SnapshotTriggerAnswer), string(api.SnapshotTriggerFork), agentActor).Scan(&due)
|
||||
)`, id, string(api.SnapshotTriggerAnswer), string(api.SnapshotTriggerFork), string(api.SnapshotTriggerAskHuman), agentActor).Scan(&due)
|
||||
return due, err
|
||||
}
|
||||
|
||||
|
||||
@@ -1664,7 +1664,7 @@ private struct SnapshotRow: View {
|
||||
.buttonStyle(SmallLinkButtonStyle())
|
||||
.disabled(forking)
|
||||
.help("Start a new task from this snapshot, its agent continuing the conversation as it stood here")
|
||||
if ![.answer, .fork].contains(snap.trigger) {
|
||||
if ![.answer, .fork, .askHuman].contains(snap.trigger) {
|
||||
reviewButton
|
||||
}
|
||||
Rectangle().fill(Palette.border).frame(height: 1)
|
||||
|
||||
@@ -160,7 +160,7 @@ private func reviewWarnings(_ taskId: String, _ store: Store, _ leave: @escaping
|
||||
async let snapsCall = client.listSnapshots(path: .init(taskId: taskId)).ok.body.json
|
||||
async let reviewsCall = client.listReviews(path: .init(taskId: taskId)).ok.body.json
|
||||
let (snaps, reviews) = try await (snapsCall, reviewsCall)
|
||||
guard let latest = snaps.last(where: { ![.answer, .fork].contains($0.trigger) }) else {
|
||||
guard let latest = snaps.last(where: { ![.answer, .fork, .askHuman].contains($0.trigger) }) else {
|
||||
return ([MergeWarning(text: "These changes haven't been reviewed")], false)
|
||||
}
|
||||
var items: [MergeWarning] = []
|
||||
|
||||
@@ -619,7 +619,7 @@ final class Store {
|
||||
try await self.loadProjects()
|
||||
}
|
||||
case "task.created", "task.title", "task.merge_title", "task.merge_queued", "task.merge_unqueued", "task.merge_after_review", "task.merge_after_review_ended", "task.merge_after_review_cancelled", "task.parent_merge_started", "task.parent_merge_stopped", "task.merge_started", "task.merge_ended", "task.discard_started", "task.merged", "task.discarded", "task.state", "task.ready", "task.discard_suggested", "task.ready_cleared", "snapshot.created":
|
||||
if let taskId = ev.taskId, ["task.merged", "task.discarded"].contains(ev.kind) || (ev.kind == "snapshot.created" && !["answer", "fork"].contains(str(ev.payload.value, "trigger"))) {
|
||||
if let taskId = ev.taskId, ["task.merged", "task.discarded"].contains(ev.kind) || (ev.kind == "snapshot.created" && !["answer", "fork", "ask_human"].contains(str(ev.payload.value, "trigger"))) {
|
||||
clearTask(self, taskId)
|
||||
}
|
||||
notifyTask(self, ev)
|
||||
|
||||
@@ -467,7 +467,7 @@ final class TranscriptBuilder {
|
||||
let snap = try! decodePayload(ev.payload, as: Snapshot.self)
|
||||
let row = Row(.snapshot(snap), taskId: taskId)
|
||||
ctx.reviewButtons[snap.n] = row
|
||||
if ![.answer, .fork].contains(snap.trigger) && sink == nil {
|
||||
if ![.answer, .fork, .askHuman].contains(snap.trigger) && sink == nil {
|
||||
lastReady = nil
|
||||
}
|
||||
put(row)
|
||||
|
||||
Reference in New Issue
Block a user