diff --git a/api/openapi.yaml b/api/openapi.yaml index e1bc604..4f4499d 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -1691,6 +1691,8 @@ components: required: [steps] properties: description: { type: string, x-go-type-skip-optional-pointer: true } + auto_merge: { type: boolean, x-go-type-skip-optional-pointer: true, description: "When a run's stage task calls ready_for_merge, byre merges it as if the human had pressed the button the agent picked, without waiting for them." } + auto_discard: { type: boolean, x-go-type-skip-optional-pointer: true, description: "When a run's stage task calls suggest_discard, byre discards it without waiting for the human." } steps: type: array minItems: 1 diff --git a/internal/agents/audit.go b/internal/agents/audit.go index d10f493..0681561 100644 --- a/internal/agents/audit.go +++ b/internal/agents/audit.go @@ -44,16 +44,6 @@ func (m *Manager) auditAll(ctx context.Context) { return } for _, p := range projects { - tasks, err := m.store.ListTasks(ctx, p.Id) - if err != nil { - slog.Error("start audits", "project", p.Id, "err", err) - continue - } - for _, t := range tasks { - if t.Status == api.TaskStatusActive && t.Background && t.State == api.TaskStateDiscardSuggested { - m.dismissAudit(t.Id) - } - } m.audit(p.Id) } } @@ -119,31 +109,5 @@ func auditBrief(branch, commit string) string { return fmt.Sprintf("Audit of %s at %s. This isn't a review of a change: check the whole codebase as it stands against the project's standards and expectations, and fix what falls short. "+ "byre runs this task in the background: the human doesn't see it until you ask a question, call ready_for_merge or hit an error. "+ "Finish your stage with finish_stage as usual, even when you found nothing. Once your stage has finished and its review has come back, byre asks whether the task is ready to merge;"+ - "if nothing needed changing, answer with suggest_discard, and byre discards the task without bothering the human.", branch, commit) -} - -func (m *Manager) dismissAudit(taskID string) { - ctx := context.Background() - task, err := m.store.GetTask(ctx, taskID) - if err != nil { - slog.Error("dismiss audit", "task", taskID, "err", err) - return - } - if !task.Background || task.Status != api.TaskStatusActive || task.WorkflowStage == nil { - return - } - output, _, err := m.store.StageResult(ctx, taskID) - if err != nil { - slog.Error("dismiss audit", "task", taskID, "err", err) - return - } - if output == "" { - return - } - _, err = m.Discard(ctx, task, "byre") - if err != nil { - slog.Error("dismiss audit", "task", taskID, "err", err) - return - } - slog.Info("audit dismissed itself", "task", taskID) + "if nothing needed changing, answer with suggest_discard.", branch, commit) } diff --git a/internal/agents/coordinator.go b/internal/agents/coordinator.go index 641c347..67ab235 100644 --- a/internal/agents/coordinator.go +++ b/internal/agents/coordinator.go @@ -93,6 +93,9 @@ func (m *Manager) coordinatePass(ctx context.Context, started map[string]bool) * for _, p := range work.ReadyPrompts { once("ready:"+p.TaskID, func() { m.promptReady(p) }) } + for _, c := range work.SelfCloses { + once(fmt.Sprintf("selfclose:%s:%s", c.TaskID, c.Ready), func() { m.selfClose(c) }) + } for _, sc := range work.DueSchedules { once(fmt.Sprintf("schedule:%s:%d", sc.Id, sc.NextRun.UnixNano()), func() { m.runSchedule(sc) }) } diff --git a/internal/agents/kb/workflow-definitions.md b/internal/agents/kb/workflow-definitions.md index 7bf8124..366be28 100644 --- a/internal/agents/kb/workflow-definitions.md +++ b/internal/agents/kb/workflow-definitions.md @@ -1,6 +1,6 @@ # Workflow definitions -A workflow's definition is an object: an optional `description`, then `steps`, which run in order. The workflow's name is not in it. `save_workflow` takes it as its `definition` argument and `read_workflow` returns it, both as JSON. Unknown fields are refused. +A workflow's definition is an object: an optional `description`, optional `auto_merge` and `auto_discard` booleans, then `steps`, which run in order. With `auto_merge`, when a stage task of a run calls `ready_for_merge`, byre merges it right away as the creator of the run, pressing the button the agent picked (`complete` or `continue`); with `auto_discard`, byre discards a stage task that calls `suggest_discard`. Without them the human decides, as for any task. The workflow's name is not in it. `save_workflow` takes it as its `definition` argument and `read_workflow` returns it, both as JSON. Unknown fields are refused. Any workflow can run on a brief, each stage as its own task, and any workflow whose stages are single agents can be a project's review workflow (set with `set_review_workflow`), which reviews its tasks' snapshots: each stage is then one reviewer agent on its `model`, given the task's change and its stage's `prompt` (what to look for), and a stage after others also gets their reviews. A project can't review with a workflow that has a team stage (`agents`). diff --git a/internal/agents/lead.go b/internal/agents/lead.go index 4a6df2c..b2b5324 100644 --- a/internal/agents/lead.go +++ b/internal/agents/lead.go @@ -376,13 +376,11 @@ func (m *Manager) Observe(events []api.Event) { switch { case (ev.Kind == "task.merged" || ev.Kind == "task.merged_to_main" || ev.Kind == "task.discarded") && ev.ProjectId != nil: go m.audit(*ev.ProjectId) - case ev.Kind == "task.discard_suggested" && ev.TaskId != nil: - go m.dismissAudit(*ev.TaskId) } switch ev.Kind { case "inbox.created", "inbox.updated", "task.created", "task.merge_queued", "task.merge_after_review", "task.merge_after_review_cancelled", "task.merge_after_review_dropped", "task.merge_started", "task.merged", "task.discarded", "turn.ended", "task.workflow_stage", "task.workflow_finished", "review.started", "review.finished", "task.state", "task.ready", "task.discard_suggested": case "task.ready_cleared": - if ev.Payload["reason"] == "merge" { + if ev.Payload["reason"] == "merge" || ev.Payload["reason"] == "discard" { continue } case "user.message": diff --git a/internal/agents/ready.go b/internal/agents/ready.go index 017c3e1..d9faf36 100644 --- a/internal/agents/ready.go +++ b/internal/agents/ready.go @@ -143,6 +143,46 @@ func (m *Manager) cancelReadyTool(l *live) mcp.Tool { } } +func (m *Manager) selfClose(c store.SelfClose) { + ctx := context.Background() + err := m.approveSelfClose(ctx, c) + if err != nil { + action := "merge" + if c.Ready == "discard" { + action = "discard" + } + slog.Error("workflow self close", "task", c.TaskID, "ready", c.Ready, "err", err) + m.fileError(ctx, c.TaskID, fmt.Sprintf("The workflow lets this task %[1]s itself, but byre couldn't %[1]s it: %[2]v. Do it by hand.", action, err)) + return + } + slog.Info("workflow self close", "task", c.TaskID, "ready", c.Ready) +} + +func (m *Manager) approveSelfClose(ctx context.Context, c store.SelfClose) error { + task, project, err := m.activeTask(ctx, c.TaskID) + if err != nil { + return err + } + taken, err := m.store.TakeReady(ctx, c.TaskID, c.Ready) + if err != nil || !taken { + return err + } + if c.Ready == "discard" { + _, err = m.Discard(ctx, task, "byre") + return err + } + user, err := m.store.GetUser(ctx, c.By) + if err != nil { + return err + } + if c.Ready == "continue" { + _, err = m.MergeToMain(ctx, task, project, user, task.MergeTitle) + return err + } + _, err = m.Merge(ctx, task, project, user, task.MergeTitle) + return err +} + func (m *Manager) promptReady(p store.ReadyPrompt) { ctx := context.Background() err := m.sendReadyPrompt(ctx, p) diff --git a/internal/agents/workflows.go b/internal/agents/workflows.go index 1a77b3e..1f88fce 100644 --- a/internal/agents/workflows.go +++ b/internal/agents/workflows.go @@ -745,6 +745,8 @@ const workflowDefinitionSchema = `{ "type": "object", "properties": { "description": {"type": "string"}, + "auto_merge": {"type": "boolean"}, + "auto_discard": {"type": "boolean"}, "steps": {"type": "array", "items": {"$ref": "#/$defs/step"}} }, "required": ["steps"], @@ -892,7 +894,7 @@ func (m *Manager) workflowTools(tool func(name, description, schema string, run tool("set_audit_workflow", "Set the audit workflow (any saved workflow) that byre runs in the background on a project's default branch: one run at a time, started whenever the branch's newest commit hasn't had one, to check the whole codebase against its standards rather than one change. "+ - "An audit's tasks stay out of list_tasks and your signals until one asks a question, calls ready_for_merge or hits an error; one that suggests discarding first is discarded by byre. An empty workflow turns audits off. Only when the human asks.", + "An audit's tasks stay out of list_tasks and your signals until one asks a question, calls ready_for_merge, hits an error, or suggests discarding in a workflow without auto_discard. An empty workflow turns audits off. Only when the human asks.", `{"type": "object", "properties": { "project_id": {"type": "string"}, "workflow": {"type": "string"} diff --git a/internal/api/api.gen.go b/internal/api/api.gen.go index 92730f2..626833e 100644 --- a/internal/api/api.gen.go +++ b/internal/api/api.gen.go @@ -1760,6 +1760,11 @@ type Weekday string // WorkflowDefinition A workflow's definition, which holds everything but its name: its steps, run in order. Run on a brief, each stage runs as its own task once the steps before it have finished; as a project's review workflow, each stage is a reviewer of a snapshot and gets the earlier stages' reviews. type WorkflowDefinition struct { + // AutoDiscard When a run's stage task calls suggest_discard, byre discards it without waiting for the human. + AutoDiscard bool `json:"auto_discard,omitempty"` + + // AutoMerge When a run's stage task calls ready_for_merge, byre merges it as if the human had pressed the button the agent picked, without waiting for them. + AutoMerge bool `json:"auto_merge,omitempty"` Description string `json:"description,omitempty"` Steps []WorkflowStep `json:"steps"` } @@ -4821,358 +4826,360 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", + "CasRiZswEQUM8B0wk9+Mkvrjx/9/AA==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/store/coordinate.go b/internal/store/coordinate.go index 37c4616..0ce67c6 100644 --- a/internal/store/coordinate.go +++ b/internal/store/coordinate.go @@ -19,6 +19,7 @@ type Work struct { StartStages []StageStart SettleReviews []SnapshotRef ReadyPrompts []ReadyPrompt + SelfCloses []SelfClose AdvanceStages []string LeadDeliveries []LeadDelivery QueuedDelivery []QueuedDelivery @@ -80,6 +81,10 @@ func (s *Store) Coordinate(ctx context.Context) (Work, error) { if err != nil { return err } + work.SelfCloses, err = selfCloses(ctx, tx) + if err != nil { + return err + } work.AdvanceStages, err = finishedStages(ctx, tx) if err != nil { return err @@ -101,3 +106,34 @@ func (s *Store) Coordinate(ctx context.Context) (Work, error) { }) return work, err } + +type SelfClose struct { + TaskID string + Ready string + By string +} + +func selfCloses(ctx context.Context, tx *sql.Tx) ([]SelfClose, error) { + rows, err := tx.QueryContext(ctx, ` + SELECT tasks.id, tasks.ready, r.created_by + FROM tasks JOIN tasks r ON r.id = tasks.parent_task_id JOIN workflow_definitions d ON d.id = r.workflow_definition_id + WHERE tasks.status = 'active' AND tasks.workflow_stage != '' AND tasks.discard_state = '' + AND tasks.merging_by = '' AND tasks.finalizing = '' AND tasks.merge_queued_by = '' AND tasks.parent_merge_by = '' AND tasks.landing_session = '' + AND ((tasks.ready IN ('complete', 'continue') AND d.auto_merge) OR (tasks.ready = 'discard' AND d.auto_discard)) + AND NOT `+implementerRunning+` + ORDER BY tasks.created_at`) + if err != nil { + return nil, err + } + defer rows.Close() + closes := []SelfClose{} + for rows.Next() { + c := SelfClose{} + err = rows.Scan(&c.TaskID, &c.Ready, &c.By) + if err != nil { + return nil, err + } + closes = append(closes, c) + } + return closes, rows.Err() +} diff --git a/internal/store/definition.go b/internal/store/definition.go index a8b7517..8922876 100644 --- a/internal/store/definition.go +++ b/internal/store/definition.go @@ -12,7 +12,7 @@ import ( func insertDefinition(ctx context.Context, tx *sql.Tx, def api.WorkflowDefinition) (string, error) { id := ids.New(ids.WorkflowDefinition) - _, err := tx.ExecContext(ctx, `INSERT INTO workflow_definitions (id, description) VALUES (?, ?)`, id, def.Description) + _, err := tx.ExecContext(ctx, `INSERT INTO workflow_definitions (id, description, auto_merge, auto_discard) VALUES (?, ?, ?, ?)`, id, def.Description, def.AutoMerge, def.AutoDiscard) if err != nil { return "", err } @@ -63,7 +63,7 @@ type stepRow struct { func loadDefinition(ctx context.Context, q querier, id string) (api.WorkflowDefinition, error) { def := api.WorkflowDefinition{} - err := q.QueryRowContext(ctx, `SELECT description FROM workflow_definitions WHERE id = ?`, id).Scan(&def.Description) + err := q.QueryRowContext(ctx, `SELECT description, auto_merge, auto_discard FROM workflow_definitions WHERE id = ?`, id).Scan(&def.Description, &def.AutoMerge, &def.AutoDiscard) if errors.Is(err, sql.ErrNoRows) { return def, fmt.Errorf("%w: no workflow definition %s", ErrNotFound, id) } diff --git a/internal/store/migrations/101-add-workflow-auto-merge.sql b/internal/store/migrations/101-add-workflow-auto-merge.sql new file mode 100644 index 0000000..306653e --- /dev/null +++ b/internal/store/migrations/101-add-workflow-auto-merge.sql @@ -0,0 +1,5 @@ +ALTER TABLE workflow_definitions ADD COLUMN auto_merge INTEGER NOT NULL DEFAULT 0; +ALTER TABLE workflow_definitions ADD COLUMN auto_discard INTEGER NOT NULL DEFAULT 0; +UPDATE workflow_definitions SET auto_discard = 1 +WHERE id IN (SELECT definition_id FROM workflows WHERE name IN (SELECT audit_workflow FROM projects WHERE audit_workflow != '')) + OR id IN (SELECT workflow_definition_id FROM tasks WHERE audit != '' AND status = 'active' AND workflow_definition_id IS NOT NULL); diff --git a/internal/store/store.go b/internal/store/store.go index cf01b99..deae1f6 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -762,6 +762,27 @@ func (s *Store) ClearReady(ctx context.Context, id, actor, reason string) error }) } +func (s *Store) TakeReady(ctx context.Context, id, ready string) (bool, error) { + taken := false + err := s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { + projectID := "" + err := tx.QueryRowContext(ctx, `UPDATE tasks SET ready = '' WHERE id = ? AND status = ? AND ready = ? RETURNING project_id`, id, string(api.TaskStatusActive), ready).Scan(&projectID) + if errors.Is(err, sql.ErrNoRows) { + return nil + } + if err != nil { + return err + } + taken = true + reason := "merge" + if ready == "discard" { + reason = "discard" + } + return emit(api.Event{Kind: "task.ready_cleared", ProjectId: &projectID, TaskId: &id, Actor: "byre", Payload: map[string]any{"id": id, "reason": reason}}) + }) + return taken, err +} + func (s *Store) setReady(ctx context.Context, id, actor, ready, kind string, payload map[string]any) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { projectID := "" @@ -1667,7 +1688,8 @@ const taskColumns = `id, project_id, title, merge_title, branch, worktree_path, // Keep the child lookup separate from the task itself so SQLite can use tasks_parent. const backgroundExpr = `(audit != '' OR EXISTS (SELECT 1 FROM tasks r WHERE r.id = tasks.parent_task_id AND tasks.workflow_stage != '' AND r.audit != '')) AND NOT EXISTS (SELECT 1 FROM events WHERE events.task_id IN (SELECT tasks.id UNION ALL SELECT c.id FROM tasks c WHERE c.parent_task_id = tasks.id AND c.parent_task_id != '' AND tasks.workflow_name != '') - AND kind IN ('inbox.created', 'task.ready', 'session.error', 'session.rate_limited'))` + AND (kind IN ('inbox.created', 'task.ready', 'session.error', 'session.rate_limited') + OR (kind = 'task.discard_suggested' AND NOT EXISTS (SELECT 1 FROM tasks r JOIN workflow_definitions d ON d.id = r.workflow_definition_id WHERE r.id IN (tasks.id, tasks.parent_task_id) AND d.auto_discard))))` const sessionColumns = `id, coalesce(task_id, ''), owner, vendor, model, vendor_session_id, state, role, member, created_by, created_at, forked_from, forked_at, subagents` diff --git a/mac/Sources/Byre/WorkflowEditor.swift b/mac/Sources/Byre/WorkflowEditor.swift index 7770184..cace7ae 100644 --- a/mac/Sources/Byre/WorkflowEditor.swift +++ b/mac/Sources/Byre/WorkflowEditor.swift @@ -176,6 +176,8 @@ struct WorkflowEditor: View { @ViewState private var loaded: WorkflowDefinition? @ViewState private var name = "" @ViewState private var description = "" + @ViewState private var autoMerge = false + @ViewState private var autoDiscard = false @ViewState private var failure = "" @ViewState private var saving = false @@ -206,6 +208,14 @@ struct WorkflowEditor: View { TextField("Description", text: $description, axis: .vertical) .modifier(FieldStyle()) .padding(.top, 8) + Toggle("Merge its tasks when they're ready", isOn: $autoMerge) + .toggleStyle(.checkbox) + .tint(Palette.accent) + .padding(.top, 8) + Toggle("Discard its tasks when they suggest it", isOn: $autoDiscard) + .toggleStyle(.checkbox) + .tint(Palette.accent) + .padding(.top, 4) if !root.stageNames().isEmpty { BoxDiagramView(source: stepDiagram(root)) .padding(.top, 12) @@ -244,7 +254,7 @@ struct WorkflowEditor: View { } private var current: WorkflowDefinition? { - root.map { WorkflowDefinition(description: description.isEmpty ? nil : description, steps: $0.children.map(\.step)) } + root.map { WorkflowDefinition(description: description.isEmpty ? nil : description, autoMerge: autoMerge ? true : nil, autoDiscard: autoDiscard ? true : nil, steps: $0.children.map(\.step)) } } private var target: String { @@ -266,6 +276,8 @@ struct WorkflowEditor: View { let def = try await store.api.client.getWorkflow(path: .init(name: original)).ok.body.json name = original description = def.description ?? "" + autoMerge = def.autoMerge ?? false + autoDiscard = def.autoDiscard ?? false root = StepNode(kind: .order, children: def.steps.map { StepNode($0) }) loaded = current } catch {