feat(merge): verify once per batch via skipVerify + verify_merges

Per-merge verify made an N-task batch pay N x ~7 min, each run testing
the same moving main. review_task/merge_task/continue_merge now take
skipVerify: the merge lands but the gate AND the Done transition are
deferred (status merged_verify_pending, task stays WaitingForReview).
The new verify_merges tool runs the list verify command once for the
explicitly listed tasks and promotes them to Done on success - explicit
ids so the handler own submitted task and parked verify_failed tasks
are never swept up; an Active worktree is refused per entry.

PlanningMergeOrchestrator threads the flag through the unit merge (no
more per-child verify) and skips FinalizeParentDoneAsync when verifies
were deferred. The merge-helper Merge prompt approves with
skipVerify=true and calls verify_merges once after the last merge. UI
approve is unchanged; the no-Done-without-green-verify invariant stays
server-enforced.
This commit is contained in:
mika kuns
2026-08-26 15:29:20 +02:00
parent c4928b4def
commit 168ab1cd2f
8 changed files with 491 additions and 41 deletions
+14 -1
View File
@@ -79,7 +79,8 @@ Task: `ListTaskLists`, `ListTasks`, `GetTask`, `AddTask`, `AddSubtask`, `UpdateT
description is now the canonical place for what each status means.)
Worktree/git: `GetTaskWorktree`, `GetTaskDiff`, `MergeTask`, `ContinueMerge`, `AbortMerge`,
`PreviewMerge`, `PreviewMergeSet`, `RevertMerge`, `ListWorktrees`, `CleanupTaskWorktree`.
`VerifyMerges`, `PreviewMerge`, `PreviewMergeSet`, `RevertMerge`, `ListWorktrees`,
`CleanupTaskWorktree`.
Daily prep: `GetDailyPrepCandidates`, `SetMyDay`.
@@ -131,6 +132,18 @@ are reported in `ReviewTaskResult`.
`Done` and merged silently with `changedFileCount: 0`, indistinguishable from a small-but-real
change. `TaskRefDto.roadblockCount` (on every task-returning tool, stamped by `TaskRunner` from
`result.Blocks.Count`) is the MCP-visible signal for *why* a child is empty.
- `skipVerify=true` (also on `MergeTask`/`ContinueMerge`) is batch mode: the merge lands but the
list's verify command is deferred and the task stays `WaitingForReview` with mergeStatus
`merged_verify_pending`. One `VerifyMerges` call after the batch runs the verify once and
promotes them — see [review-merge.md](review-merge.md) → batch verify.
**`VerifyMerges`** — `verify_merges(taskIds)`: runs the list's verify command ONCE (same per-repo
merge gate) and promotes each listed task to Done via `ApproveReviewAsync` on success. Explicit
ids on purpose — auto-promoting every `WaitingForReview` task would sweep up the handler's own
task and deliberately parked `verify_failed` tasks. Eligibility per task: `WaitingForReview` AND
(worktree `Merged` OR no worktree); an `Active` worktree means the branch never landed and is
refused per-entry (the rest still promote). All ids must share one list. `verify_failed` promotes
nothing; the merges stay in place.
**`PreviewMerge`** — non-destructive `git merge-tree --write-tree` mergeability check for one
task's worktree branch against `targetBranch` (default: the repo's current branch). Returns