diff --git a/api/openapi.yaml b/api/openapi.yaml index d57709f..ad0bc8a 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -1385,9 +1385,9 @@ components: background: { type: boolean, description: "Whether the task is an audit that hasn't asked for attention yet: no question, ready_for_merge or error so far. The app keeps it out of the task switcher and shows it muted on the Project tab, and the lead gets no signals about it." } state: type: string - description: "The one state the task is in, kept by the store in the same transaction as every change to it (a task.state event carries each change). The first that holds: merged or discarded once closed; discarding; asking while it has an open question; merging while a Merge or a merge into its parent is under way; merge_held while its Merge waits for another merge in the project; merge_after_review while a Merge with after_review waits for its review; running while one of its agents is mid-turn or has subagents running; reviewing while a review runs; review_pending between a turn's end and its snapshot's review starting or being skipped; ready_to_merge or discard_suggested when the agent's latest ready_for_merge or suggest_discard still stands; idle; no_agent when it has no live agent." - enum: [running, idle, review_pending, reviewing, merging, discarding, merged, discarded, no_agent, asking, merge_held, merge_after_review, ready_to_merge, discard_suggested] - x-enum-varnames: [TaskStateRunning, TaskStateIdle, TaskStateReviewPending, TaskStateReviewing, TaskStateMerging, TaskStateDiscarding, TaskStateMerged, TaskStateDiscarded, TaskStateNoAgent, TaskStateAsking, TaskStateMergeHeld, TaskStateMergeAfterReview, TaskStateReadyToMerge, TaskStateDiscardSuggested] + description: "The one state the task is in, kept by the store in the same transaction as every change to it (a task.state event carries each change). The first that holds: merged or discarded once closed; discarding; asking while it has an open question; merging while a Merge or a merge into its parent is under way; merge_held while its Merge waits for another merge in the project; merge_after_review while a Merge with after_review waits for its review; running while one of its agents is mid-turn or has subagents running; reviewing while a review runs; review_pending between a turn's end and its snapshot's review starting or being skipped; ready_to_merge or discard_suggested when the agent's latest ready_for_merge or suggest_discard still stands; finished when it runs a workflow stage whose finish_stage has taken; idle; no_agent when it has no live agent." + enum: [running, idle, finished, review_pending, reviewing, merging, discarding, merged, discarded, no_agent, asking, merge_held, merge_after_review, ready_to_merge, discard_suggested] + x-enum-varnames: [TaskStateRunning, TaskStateIdle, TaskStateFinished, TaskStateReviewPending, TaskStateReviewing, TaskStateMerging, TaskStateDiscarding, TaskStateMerged, TaskStateDiscarded, TaskStateNoAgent, TaskStateAsking, TaskStateMergeHeld, TaskStateMergeAfterReview, TaskStateReadyToMerge, TaskStateDiscardSuggested] merging: { type: boolean, description: "Whether a Merge was started and hasn't finished: its turn is running, or the turn ended and byre is squashing, pushing and closing the task." } discarding: { type: boolean, description: "Whether a Discard was started and the task isn't closed yet: its summary turn is waiting for the running turn, running, or done and the task is being removed." } parent_task_id: { type: string, description: "The task whose agent created this one as its subtask; absent for other tasks." } diff --git a/internal/agents/lead.go b/internal/agents/lead.go index afa5199..bd38d13 100644 --- a/internal/agents/lead.go +++ b/internal/agents/lead.go @@ -14,7 +14,7 @@ import ( ) const leadGuidance = `You are the human's lead agent in byre, shown in the left pane of byre's app. The human talks to you there, and you coordinate every task agent on their behalf. You don't do task work yourself: task agents work in their own worktrees, and you read, direct and report on them. -- Signals: byre sends you, as messages from byre, what happens across tasks: questions that task agents ask, errors and rate limits their sessions hit, turns they finish with their final message, a task's agent saying the task is ready to merge (with its overview of the whole task, which byre asks for once the review of its latest work has finished and its turn has ended) or suggesting the human discard it (with its reasoning), questions the human answered, tasks created, reviews started and finished, a merge held behind another task's or set to start after the review (and that canceled or dropped), starting to merge, merged or discarded, and every change of a task's state, as " state: → ." listed first among what happened at the same moment. State changes, reviews starting, and tasks the human created, started merging, merged or discarded never wake you on their own; they arrive only alongside another signal. The states are running, idle, review_pending, reviewing, merging, discarding, merged, discarded and no_agent. A finished turn arrives with its state change: review_pending when byre is about to review the turn's work, reviewing while the review runs; neither is done, since the review can still find problems, so don't treat a task's work as finished until its state goes to idle. Several may arrive in one message, followed by the current task list (as list_tasks gives it) and what your right pane shows, so you rarely need to call list_tasks after a signal. The human doesn't see signals. Messages from the human arrive separately. +- Signals: byre sends you, as messages from byre, what happens across tasks: questions that task agents ask, errors and rate limits their sessions hit, turns they finish with their final message, a task's agent saying the task is ready to merge (with its overview of the whole task, which byre asks for once the review of its latest work has finished and its turn has ended) or suggesting the human discard it (with its reasoning), questions the human answered, tasks created, reviews started and finished, a merge held behind another task's or set to start after the review (and that canceled or dropped), starting to merge, merged or discarded, and every change of a task's state, as " state: → ." listed first among what happened at the same moment. State changes, reviews starting, and tasks the human created, started merging, merged or discarded never wake you on their own; they arrive only alongside another signal. The states are running, idle, finished (a workflow stage's task once its finish_stage has taken), review_pending, reviewing, merging, discarding, merged, discarded and no_agent. A finished turn arrives with its state change: review_pending when byre is about to review the turn's work, reviewing while the review runs; neither is done, since the review can still find problems, so don't treat a task's work as finished until its state goes to idle or finished. Several may arrive in one message, followed by the current task list (as list_tasks gives it) and what your right pane shows, so you rarely need to call list_tasks after a signal. The human doesn't see signals. Messages from the human arrive separately. - Don't respond to what the human just did. A signal about their own action (a question they answered, a task they created, merged, started merging or discarded) tells them nothing new: don't report, confirm or comment on it. Act on it only if it changes what you are doing, and then end the turn with one short line at most. When a batch of signals needs nothing from you to the human, make your final message exactly NO_REPLY and nothing else; byre folds that turn away so the human doesn't see it. - "Your right pane is free" means the human finished what was in the right pane. Show them the next thing that needs them, most urgent first (questions, then errors on the task's transcript tab, then finished turns, then tasks ready to merge or suggested for discarding), with one line saying what it is. If nothing needs them, show that project's project tab, then post a short status: one line per active task (what it's doing or waiting on), then up to three TODO items you'd start next (from list_tasks), each with a one-line reason. Write each item as a link to #/todo//, for example [Fix login redirect](#/todo/3f2a9c1b7d4e/Fix%20login%20redirect): byre draws it with a Start button the human can click, and once the task exists, its state. Start one with start_todo only when the human picks it. If that says nothing new since your last status, make your final message NO_REPLY. - Whenever you suggest new work that isn't in TODO.md (a task you think is worth doing, an improvement to byre or to your own role), write it as a link to #/suggest///<brief>, both URL-encoded with parentheses as %28 and %29, for example [Lead tool for admin status](#/suggest/3f2a9c1b7d4e/Lead%20tool%20for%20admin%20status/Add%20a%20lead%20tool%20that%20reads%20%2Fapi%2Fadmin%2Fstatus%20...). The brief is the new task agent's whole first message, so make it a complete brief, as for create_task. byre draws the link with two buttons: Start creates the task with that title and brief at once, without you, and Discuss sends you a message asking to talk the suggestion over. Once an active task has that title, it shows the task's state instead. Don't ask whether to start a suggestion; the buttons do that. diff --git a/internal/agents/ready.go b/internal/agents/ready.go index fec8a4e..811073e 100644 --- a/internal/agents/ready.go +++ b/internal/agents/ready.go @@ -143,7 +143,7 @@ func (m *Manager) cancelReadyTool(l *live) mcp.Tool { } func readyState(s api.TaskState) bool { - return s == api.TaskStateIdle || s == api.TaskStateReadyToMerge || s == api.TaskStateDiscardSuggested + return s == api.TaskStateIdle || s == api.TaskStateFinished || s == api.TaskStateReadyToMerge || s == api.TaskStateDiscardSuggested } func (m *Manager) promptReady(taskID string, from any) { diff --git a/internal/api/api.gen.go b/internal/api/api.gen.go index ca777b9..fb0ce70 100644 --- a/internal/api/api.gen.go +++ b/internal/api/api.gen.go @@ -414,6 +414,7 @@ const ( TaskStateDiscardSuggested TaskState = "discard_suggested" TaskStateDiscarded TaskState = "discarded" TaskStateDiscarding TaskState = "discarding" + TaskStateFinished TaskState = "finished" TaskStateIdle TaskState = "idle" TaskStateMergeAfterReview TaskState = "merge_after_review" TaskStateMergeHeld TaskState = "merge_held" @@ -437,6 +438,8 @@ func (e TaskState) Valid() bool { return true case TaskStateDiscarding: return true + case TaskStateFinished: + return true case TaskStateIdle: return true case TaskStateMergeAfterReview: @@ -1341,7 +1344,7 @@ type Task struct { PortBase int `json:"port_base"` ProjectId string `json:"project_id"` - // State The one state the task is in, kept by the store in the same transaction as every change to it (a task.state event carries each change). The first that holds: merged or discarded once closed; discarding; asking while it has an open question; merging while a Merge or a merge into its parent is under way; merge_held while its Merge waits for another merge in the project; merge_after_review while a Merge with after_review waits for its review; running while one of its agents is mid-turn or has subagents running; reviewing while a review runs; review_pending between a turn's end and its snapshot's review starting or being skipped; ready_to_merge or discard_suggested when the agent's latest ready_for_merge or suggest_discard still stands; idle; no_agent when it has no live agent. + // State The one state the task is in, kept by the store in the same transaction as every change to it (a task.state event carries each change). The first that holds: merged or discarded once closed; discarding; asking while it has an open question; merging while a Merge or a merge into its parent is under way; merge_held while its Merge waits for another merge in the project; merge_after_review while a Merge with after_review waits for its review; running while one of its agents is mid-turn or has subagents running; reviewing while a review runs; review_pending between a turn's end and its snapshot's review starting or being skipped; ready_to_merge or discard_suggested when the agent's latest ready_for_merge or suggest_discard still stands; finished when it runs a workflow stage whose finish_stage has taken; idle; no_agent when it has no live agent. State TaskState `json:"state"` Status TaskStatus `json:"status"` @@ -1365,7 +1368,7 @@ type Task struct { WorktreePath string `json:"worktree_path"` } -// TaskState The one state the task is in, kept by the store in the same transaction as every change to it (a task.state event carries each change). The first that holds: merged or discarded once closed; discarding; asking while it has an open question; merging while a Merge or a merge into its parent is under way; merge_held while its Merge waits for another merge in the project; merge_after_review while a Merge with after_review waits for its review; running while one of its agents is mid-turn or has subagents running; reviewing while a review runs; review_pending between a turn's end and its snapshot's review starting or being skipped; ready_to_merge or discard_suggested when the agent's latest ready_for_merge or suggest_discard still stands; idle; no_agent when it has no live agent. +// TaskState The one state the task is in, kept by the store in the same transaction as every change to it (a task.state event carries each change). The first that holds: merged or discarded once closed; discarding; asking while it has an open question; merging while a Merge or a merge into its parent is under way; merge_held while its Merge waits for another merge in the project; merge_after_review while a Merge with after_review waits for its review; running while one of its agents is mid-turn or has subagents running; reviewing while a review runs; review_pending between a turn's end and its snapshot's review starting or being skipped; ready_to_merge or discard_suggested when the agent's latest ready_for_merge or suggest_discard still stands; finished when it runs a workflow stage whose finish_stage has taken; idle; no_agent when it has no live agent. type TaskState string // TaskStatus defines model for Task.Status. @@ -4352,187 +4355,188 @@ var swaggerSpec = []string{ "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", + "bkJNHDC8aMR+fDGKqg8f/tcA", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/store/migrations/083-add-finished-task-state.sql b/internal/store/migrations/083-add-finished-task-state.sql new file mode 100644 index 0000000..604cfcc --- /dev/null +++ b/internal/store/migrations/083-add-finished-task-state.sql @@ -0,0 +1 @@ +UPDATE tasks SET state = 'finished' WHERE state = 'idle' AND stage_output != ''; diff --git a/internal/store/store.go b/internal/store/store.go index 9597348..33584f1 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -1631,6 +1631,7 @@ const taskStateExpr = `CASE WHEN tasks.review_requests > 0 THEN 'review_pending' WHEN tasks.ready = 'merge' THEN 'ready_to_merge' WHEN tasks.ready = 'discard' THEN 'discard_suggested' + WHEN tasks.stage_output != '' THEN 'finished' ELSE 'idle' END FROM agent_sessions s diff --git a/internal/store/workflow.go b/internal/store/workflow.go index 012eb37..dc6e846 100644 --- a/internal/store/workflow.go +++ b/internal/store/workflow.go @@ -205,7 +205,10 @@ func (s *Store) RunEvents(ctx context.Context, run string) ([]api.Event, error) func (s *Store) RecordStage(ctx context.Context, taskID, output, commit string) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { _, err := tx.ExecContext(ctx, `UPDATE tasks SET stage_output = ?, stage_commit = ? WHERE id = ?`, output, commit, taskID) - return err + if err != nil { + return err + } + return settleTaskState(ctx, tx, emit, taskID, "byre") }) } diff --git a/mac/Sources/Byre/Store.swift b/mac/Sources/Byre/Store.swift index 71be599..a2452ac 100644 --- a/mac/Sources/Byre/Store.swift +++ b/mac/Sources/Byre/Store.swift @@ -45,6 +45,7 @@ private let stateTitles: [ByreTask.StatePayload: TaskState] = [ .readyToMerge: TaskState(kind: .ready, label: "Ready to merge", title: "The agent says the task is ready to merge"), .discardSuggested: TaskState(kind: .ready, label: "Ready to discard", title: "The agent suggests discarding the task"), .idle: TaskState(kind: .idle, label: "Idle", title: "Waiting for a message"), + .finished: TaskState(kind: .idle, label: "Finished", title: "The workflow stage finished"), .noAgent: TaskState(kind: .idle, label: "Idle", title: "Waiting for a message"), .merged: TaskState(kind: .idle, label: "Merged", title: "The task was merged"), .discarded: TaskState(kind: .idle, label: "Discarded", title: "The task was discarded"),