Open merge dialog instantly from pushed merge facts

This commit is contained in:
Ian Gulliver
2026-10-21 11:48:21 -07:00
parent 4bb6f1fa11
commit 890fb6b691
15 changed files with 736 additions and 678 deletions
+25 -42
View File
@@ -466,40 +466,6 @@ paths:
schema: { $ref: "#/components/schemas/WorkflowRun" }
"404": { $ref: "#/components/responses/Error" }
/api/tasks/{taskId}/unmerged:
parameters:
- { name: taskId, in: path, required: true, schema: { type: string } }
get:
operationId: getUnmerged
description: What the task's worktree holds that its project's default branch doesn't.
responses:
"200":
description: The unmerged changes.
content:
application/json:
schema: { $ref: "#/components/schemas/Unmerged" }
"404": { $ref: "#/components/responses/Error" }
"409": { $ref: "#/components/responses/Error" }
/api/tasks/{taskId}/co-authors:
parameters:
- { name: taskId, in: path, required: true, schema: { type: string } }
get:
operationId: getCoAuthors
description: >
The humans other than the caller with a message in the task's transcript (sent its agent a message, or had
an inbox answer delivered under their name), in order of their first message. A merge by the caller gives each one with a git identity a
Co-authored-by trailer.
responses:
"200":
description: The co-authors.
content:
application/json:
schema:
type: array
items: { $ref: "#/components/schemas/Participant" }
"404": { $ref: "#/components/responses/Error" }
/api/tasks/{taskId}/merge:
parameters:
- { name: taskId, in: path, required: true, schema: { type: string } }
@@ -1478,7 +1444,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, state, merging, discarding, merging_into_parent, merge_after_review, summary_seq, background]
required: [id, project_id, title, merge_title, branch, worktree_path, base_ref, port_base, color, status, created_by, created_at, state, merging, discarding, merging_into_parent, merge_after_review, summary_seq, background, merge_facts]
properties:
id: { type: string }
project_id: { type: string }
@@ -1516,6 +1482,7 @@ components:
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." }
merge_after_review: { type: boolean, description: "Whether a Merge with after_review is waiting for the running review of the latest snapshot to finish." }
summary_seq: { type: integer, format: int64, description: "The seq of the task's latest turn.ended event with summary: true; 0 when it has none." }
merge_facts: { $ref: "#/components/schemas/MergeFacts" }
Todo:
type: object
@@ -1542,15 +1509,31 @@ components:
model: { type: string }
discuss: { type: boolean, description: "Tell the agent the human wants to discuss the item in chat before anything is built." }
Unmerged:
MergeFacts:
type: object
required: [commits, files, insertions, deletions, uncommitted]
description: >
What a Merge of the task would land and how far it's been reviewed. The store keeps it on the task and
recomputes it only on events that can change it (a turn ending, a snapshot, a review starting, finishing or
having a finding answered, a human's message, the project's default branch moving, a user's git identity
changing); a task.merge_facts event, whose payload is the new MergeFacts, carries each change, and none is
sent when nothing changed.
required: [unmerged_commits, unmerged_files, unreviewed_changes, review_snapshot, review_count, review_running, review_failed, review_findings, participants]
properties:
commits: { type: integer, description: Commits on the task branch that aren't on the default branch. }
files: { type: integer, description: Files that differ from the merge base, uncommitted changes included. }
insertions: { type: integer }
deletions: { type: integer }
uncommitted: { type: integer, description: Paths with uncommitted changes in the worktree. }
unmerged_commits: { type: integer, description: Commits on the task branch that aren't on the default branch. }
unmerged_files: { type: integer, description: "Files that differ from the merge base, uncommitted changes included." }
unreviewed_changes: { type: boolean, description: Whether the worktree differs from the latest reviewable snapshot. }
review_snapshot: { type: integer, description: "The n of the latest snapshot that isn't a cut point (answer, fork, ask_human); 0 when there is none." }
review_count: { type: integer, description: The number of reviews of review_snapshot. }
review_running: { type: boolean, description: Whether a review of review_snapshot is running. }
review_failed: { type: boolean, description: Whether a review of review_snapshot failed. }
review_findings: { type: integer, description: "Findings of review_snapshot's finished reviews that aren't ignored." }
participants:
type: array
description: >
The humans with a message in the task's transcript (sent its agent a message, or had an inbox answer
delivered under their name), in order of their first message. A merge gives each one other than the
merger with a git identity a Co-authored-by trailer.
items: { $ref: "#/components/schemas/Participant" }
Participant:
type: object