Let task agents create and manage subtasks

This commit is contained in:
Ian Gulliver
2026-10-16 10:36:38 -07:00
parent fd63a0dfbc
commit 0f2415570c
30 changed files with 1067 additions and 287 deletions
+17 -6
View File
@@ -299,7 +299,12 @@ paths:
checkout to it, then removes the worktree and branch and marks the task merged. While another task in the
project is merging, the merge is held instead (merge_queued_at is set) and starts when no merge is in progress
in the project and the task's session is idle, oldest first. The title is fixed from here until the task
closes. Refused while a turn is running, or the merge is already held.
closes. Refused while a turn is running, or the merge is already held. With target parent, for a subtask
only, the subtask's branch is merged into its parent task's branch instead: the parent's agent is asked to
merge it (queued if it is mid-turn), and the subtask closes as merged once its branch is in the parent's
HEAD at the end of one of the parent's turns (merging_into_parent is set until then). Refused while the
subtask's turn is running or it is already merging into its parent. Either target is refused while the
task has active subtasks of its own.
requestBody:
required: true
content:
@@ -307,9 +312,13 @@ paths:
schema:
type: object
additionalProperties: false
required: [merge_title]
properties:
merge_title: { type: string, description: "The squash commit's title: one line, at most 72 characters." }
merge_title: { type: string, description: "The squash commit's title: one line, at most 72 characters. Required for target main." }
target:
type: string
enum: [main, parent]
x-enum-varnames: [MergeTargetMain, MergeTargetParent]
description: "main (the default): squash onto the project's default branch. parent: merge into the parent task's branch; only for a subtask."
responses:
"202":
description: The merge was started or held.
@@ -349,8 +358,8 @@ paths:
idle (or in a new session when it has none) and otherwise as soon as the running turn ends, with no other
turn admitted meanwhile; drops any held merge; and when that turn ends however it ends, removes the task's
worktree and branch without merging and marks the task discarded. The task's record, summary and events
remain. Refused while the task is merging or already being discarded; on a task whose cleanup failed, retries
the cleanup.
remain. Refused while the task is merging, already being discarded, or has active subtasks; on a task whose
cleanup failed, retries the cleanup.
responses:
"202":
description: The task, still active, whose discard was started.
@@ -914,7 +923,7 @@ components:
Task:
type: object
required: [id, project_id, title, merge_title, branch, worktree_path, base_ref, port_base, color, status, created_by, created_at, reviewing, merging, discarding]
required: [id, project_id, title, merge_title, branch, worktree_path, base_ref, port_base, color, status, created_by, created_at, reviewing, merging, discarding, merging_into_parent]
properties:
id: { type: string }
project_id: { type: string }
@@ -943,6 +952,8 @@ components:
reviewing: { type: boolean, description: "Whether a review of one of the task's snapshots is running." }
merging: { type: boolean, description: "Whether a Merge was started and its turn hasn't ended yet." }
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." }
merging_into_parent: { type: boolean, description: "Whether a merge of this subtask into its parent was requested and the parent hasn't merged it yet." }
Todo:
type: object