name: legion-reconciler description: Merge shipped PRs in dependency order, invoking the mediator on conflicts. Used by the orchestrator after workers finish, or manually via /legion-reconcile. Runs one idempotent pass per invocation — call repeatedly while reconcile has work to do.
legion-reconciler
Dependency-ordered PR merging. Mediator-aware.
Flow per invocation
One pass:
legion reconcilefinds tasks whose status ==shipped, have apr_url, have nomerge_blocker, and whose deps are allmerged.- For each:
- CI check (
gh pr checks <pr-number>):pending→ skip this tick, try again next passfail→ markmerge_blocker = "ci_failed", surface to userpassornone→ proceed
- Merge attempt (
gh pr merge --squash --delete-branch):merged→ markmerged_at = now()conflict→ invoke mediator (see below)gh_error→ markmerge_blocker = "gh_error", surface
- CI check (
- Emit a JSON list of actions taken.
The reconciler is idempotent. You can (and should) call legion reconcile repeatedly while there are shipped-but-unmerged tasks. In the orchestrator's main loop, interleave legion poll (worker status) with legion reconcile (PR status).
Mediator fallback
On merge conflict:
- Increment
task.mediator_attempts. - If attempts >
config.reconciler.mediator_max_retries(default 2), markmerge_blocker = "mediator_maxed"and stop. - Otherwise call
mediator.run_mediator(task, base_branch):- Creates a fresh worktree at
.legion/mediators/<task-id>/offorigin/<base>. git merge origin/<task.branch>— forces conflict markers to appear.- Spawns
claude -pwith a mediator-framed prompt (preserve both intents, don't revert main's commits, don't touch unrelated files). - On clean exit + no remaining
<<<<<<<markers: commit + force-push totask.branch. - Retry
gh pr mergeonce.
- Creates a fresh worktree at
If the mediator resolves the conflict and the retry merge succeeds: task status becomes mediated_and_merged.
If the mediator leaves conflicts or fails: mediation_failed with detail, task gets a blocker, surface to user.
When to invoke from a skill
- After orchestrator's dispatch loop finishes — shipped tasks accumulate; drain them with reconcile.
- Interleaved inside the dispatch loop — as workers finish, merge them immediately so downstream deps can start.
- Manually —
/legion-reconcilefor a one-shot,legion mediate <task-id>to re-run the mediator on a specific task.
Failure surfaces
merge_blocker = "ci_failed": user's CI is telling the task it's broken. Orchestrator should NOT re-dispatch automatically — the code is wrong, not the run. Surface to user with the PR URL + check detail.merge_blocker = "mediator_maxed": the mediator triedmediator_max_retriestimes and couldn't resolve. Surface the PR + the mediator log (.legion/mediator_logs/<task-id>.log) and ask the user to resolve manually.merge_blocker = "needs_human": reserved for Phase 4 — user explicitly escalated.merge_blocker = "gh_error": gh CLI returned an error we don't know how to classify. Usually means auth, rate limit, or branch state issues. Show the raw error.
Subcommands used
legion reconcile # one idempotent pass
legion mediate <task-id> # force mediator run on a task
legion status # shows merged/unmerged/blocked