Skip to content

feat: Branch & PR Reconciler — auto-finish this machine's unfinished branches/PRs#2237

Merged
atomantic merged 10 commits into
mainfrom
feat/branch-pr-reconciler
Jul 6, 2026
Merged

feat: Branch & PR Reconciler — auto-finish this machine's unfinished branches/PRs#2237
atomantic merged 10 commits into
mainfrom
feat/branch-pr-reconciler

Conversation

@atomantic

Copy link
Copy Markdown
Owner

Branch & PR Reconciler

A daily, opt-in CoS automation that finishes this machine's unfinished git work — cleaning up merged/orphaned local branches + worktrees deterministically, and dispatching one coordinator CoS agent (which orchestrates one sub-agent per branch) to finish in-flight PRs — while never touching a federated peer's branches.

The problem it solves

CoS agents, /do:next swarms, and human /claim sessions routinely leave a machine with: local branches whose PRs already merged (branch + worktree linger), pushed branches with no PR, PRs stuck on conflicts, and green PRs that never got merged. Today you manually prompt Claude to "look at the open PRs and branches and finish the work." This automates that.

Peer-safety guarantee

Multiple federated machines push branches and open PRs to the same GitHub repo, all as the same GitHub user. The reconciler only ever enumerates local refs/heads/ branches in this clone — a peer's branch exists here only as origin/*, so it is structurally invisible. Authorship is deliberately not used (can't distinguish your machines from each other); local-branch existence can.

How it works — two-tier hybrid

Tier 1 (deterministic, no LLM): enumerate local branches + worktrees, classify each (MERGED / CONFLICTED / IN_REVIEW / NEEDS_PR / WIP), and clean up fully-merged orphans (remove worktree + delete local branch) behind hard safety gates — a branch is deleted only when isBranchMergedInto(default) re-verifies true and its worktree is clean. A dirty worktree is always WIP (never handed to an agent that could rebase over uncommitted work).

Tier 2 (agent): when in-flight branches remain, enqueue one coordinator CoS task that dispatches a sub-agent per branch (in that branch's existing worktree) to open PRs (after verifying the work is complete), resolve conflicts, drive review loops, and auto-merge when fully green (MERGEABLE + CI green + latest Copilot review = 0 comments). A stable dedup description prevents stacking coordinators across daily runs.

Wiring

  • server/services/branchReconcile.js — pure classifier + deterministic cleanup (unit-tested).
  • server/services/branchReconcileScheduler.js — daily cron via eventScheduler (backupScheduler pattern); re-reads settings each run; enqueues the coordinator.
  • settings.jsonbranchReconcile { enabled, cron, actions }disabled by default (honors "no cold-bootstrap LLM calls"); Zod-validated slice; seeded in data.reference/.
  • POST /api/branch-reconcile/run (manual, force) + GET /status.
  • Settings → Branch Reconcile tab (toggle, cron, per-action checkboxes, Run Now gated on saved-enabled, last-run summary) + nav-manifest entry.

Reporting honesty

The run summary reports queued + coordinatorWillRun + cosAutonomy — the coordinator only actually spawns when CoS auto-run is in Execute mode, and the UI warns when it's queued but won't run.

Tests

Full server suite green (16.7k tests). New: branchReconcile.test.js, branchReconcileScheduler.test.js, routes/branchReconcile.test.js, BranchReconcileTab.test.jsx, plus branchReconcileConfigSchema cases.

Reviewed

Local code review + /simplify + claude reviewer (3 findings fixed: dirty-worktree protection, honest dispatch reporting, cron validation) + codex reviewer.

Design docs: docs/plans/2026-07-06-branch-pr-reconciler.md, docs/superpowers/plans/2026-07-06-branch-pr-reconciler.md.

https://claude.ai/code/session_01UAyTqLdBCLfb2JXCApBc3m

atomantic added 10 commits July 6, 2026 07:58
Scheduled, opt-in CoS automation that reconciles this machine's unfinished
git work (clean up merged/orphaned branches + worktrees deterministically;
dispatch a coordinator agent to finish in-flight PRs) while never touching
federated peers' branches (local-branch-existence discriminator).

Claude-Session: https://claude.ai/code/session_01UAyTqLdBCLfb2JXCApBc3m
Tier 1 core: enumerate this machine's local branches, classify by merge/PR
state, and clean up fully-merged orphans (remove worktree + delete branch)
behind safety gates. Peer branches (origin/* only) are structurally
invisible. Returns in-flight set for the coordinator agent.

Claude-Session: https://claude.ai/code/session_01UAyTqLdBCLfb2JXCApBc3m
Opt-in config (enabled/cron/actions), disabled by default. Validated on the
settings PUT slice; default seeded in data.reference/settings.json.

Claude-Session: https://claude.ai/code/session_01UAyTqLdBCLfb2JXCApBc3m
Daily cron (opt-in) runs Tier-1 reconcile, then enqueues one coordinator CoS
task for the actionable in-flight branches. Action toggles gate per-state
dispatch; a stable dedup description prevents stacking coordinators. Manual
runs pass force to bypass the enabled gate.

Claude-Session: https://claude.ai/code/session_01UAyTqLdBCLfb2JXCApBc3m
POST /api/branch-reconcile/run (force) + GET /status; scheduler registered
at boot (no-op unless enabled).

Claude-Session: https://claude.ai/code/session_01UAyTqLdBCLfb2JXCApBc3m
Settings → Branch Reconcile: enable toggle, cron, per-action checkboxes,
Run Now (gated on saved-enabled + clean), last-run summary. Registered in
the settings tabs + nav manifest.

Claude-Session: https://claude.ai/code/session_01UAyTqLdBCLfb2JXCApBc3m
/simplify pass: remove the unused `merged` field from reconcile()'s return
(merged branches surface via `skipped` when cleanup is off) and combine the
two cosTaskStore imports.

Claude-Session: https://claude.ai/code/session_01UAyTqLdBCLfb2JXCApBc3m
…orting, validate cron

- classifyBranch: a worktree with real uncommitted changes is WIP regardless of
  PR state — never hand a dirty tree to the coordinator (its rebase/merge could
  stash/reset and discard the user's in-progress work).
- runBranchReconcile: report `queued` + `coordinatorWillRun` + `cosAutonomy` so
  the UI doesn't claim an agent ran when the coordinator is only queued and the
  CoS runner won't spawn it unless auto-run is in Execute mode.
- branchReconcileConfigSchema: validate cron is 5-6 fields so a malformed save
  can't throw out of the boot-time scheduler registration.

Claude-Session: https://claude.ai/code/session_01UAyTqLdBCLfb2JXCApBc3m
…ion, surface run errors

- cleanupMerged: never tear down a locked / human-/claim / active-CoS-agent
  worktree even when its branch is merged + clean (worktreeProtectionReason
  guard; activeAgentIds threaded from the scheduler). Was removing the worktree
  before deleteBranch's checked-out protection could apply.
- cron: schema now requires exactly 5 fields; the settings route range-validates
  via eventScheduler's own isValidCron so `99 99 * * *` (accepted by field count
  but unrunnable) is rejected 400 instead of registering a job that never fires.
- BranchReconcileTab: the server returns HTTP 200 { error } on a caught run
  failure, so check summary.error before the success toast.

Claude-Session: https://claude.ai/code/session_01UAyTqLdBCLfb2JXCApBc3m
@atomantic atomantic merged commit 8e48e54 into main Jul 6, 2026
1 of 2 checks passed
@atomantic atomantic deleted the feat/branch-pr-reconciler branch July 6, 2026 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant