Status: proposed canonical execution plan
Date: 2026-08-28
Scope: comprehensive algorithm for converging the repository’s branch population into one trustworthy canonical main
This document operationalizes BRANCH_CONVERGENCE_POLICY.md.
The repository has accumulated a large branch population through fast parallel experimentation. The goal is not to merge every branch. The goal is to make every branch reach one explicit terminal state:
integrated into main
OR superseded/retired
OR preserved as evidence
OR actively blocked with a named gate
The plan therefore treats branch convergence as a controlled graph-reduction problem, not a bulk Git operation.
At the start of this plan:
main: 523b10819abe1e88ce0207665098248ac0ed980b;main;main.protected = false;This is a point-in-time snapshot, not an invariant. IDKMesh changes quickly, so every irreversible action must re-read live repository state.
Define the non-default branch set at time t as B_t.
For every branch b in B_t, assign exactly one lifecycle decision:
D(b) in {
INTEGRATE_VIA_PR,
PREPARE_CURRENT_MAIN_REPLACEMENT,
PRESERVE_EVIDENCE,
HOLD,
RETIRE
}
The optimization target is not minimum branch count by itself.
A better repository objective is:
ConvergenceQuality =
canonical useful work
+ preserved falsification/evidence
+ explicit blocker visibility
- duplicate responsibility
- stale ancestry risk
- reviewer/conflict debt
- branch ambiguity
A branch disappears only after its useful or evidentiary information has a durable home.
branch exists != branch should merge
branch ahead != branch should merge
branch diverged != branch should merge
CI green != independent approval
worker/verifier success != integration decision
Substantive canonical integration must flow through:
branch
-> pull request
-> exact-head diff/evidence/review
-> explicit integration decision
-> main
No stale branch is directly merged merely to reduce branch count.
Squash merging means the source ref may remain ahead or diverged even though its reviewed content is already canonical.
Therefore:
current branch head == merged PR head
-> RETIRE lane
-> NEVER second merge
If evidence names branch head H:
EvidenceValid = (current_head == H)
Rebase, force-update, merge-from-main, or any other head movement requires evidence to be deliberately rebound/re-executed as appropriate.
A priority score can order eligible work. It cannot override a missing safety/review/evidence gate.
Any merge changes the canonical base and can change:
Therefore merge planning is transactional rather than batched.
The merge system uses three related graphs.
Nodes: Git refs / branches.
Edges: PR history and replacement/supersession relationships.
Purpose: answer whether a branch is active, integrated, stale, evidentiary, or cleanup-ready.
Nodes: active/replacement PRs.
Directed edge:
A -> B
means B must not integrate before A.
Dependencies may come from:
No dependency edge should be inferred solely from similar prose or branch names.
Nodes: branches/PRs that attempt the same project responsibility.
Examples:
Purpose: prevent multiple obsolete implementations from all eventually reaching main.
Rule:
one canonical implementation per responsibility
When a newer reviewed lineage supersedes an older one, the older branch moves to RETIRE or PRESERVE_EVIDENCE, not to the merge queue.
The existing branch_convergence_audit.py remains the source classifier.
The merge planner maps its states into five action lanes.
| Audit state | Merge-plan lane | Allowed next operation |
|---|---|---|
active-review-pr |
PR integration review | evaluate hard PR gate |
active-draft-pr |
hold | satisfy explicit blocker |
open-pr-head-mismatch |
hold | refresh exact-head metadata/evidence |
ambiguous-open-prs |
hold | choose/split canonical PR |
integrated-via-pr |
retirement | never merge again |
post-merge-branch-moved |
extract or retire | inspect only post-merge delta |
closed-unmerged-no-unique-commits |
retirement | retire after reference check |
closed-unmerged-evidence-branch |
evidence preservation | preserve evidence, then retire/extract |
closed-unmerged-unique-work |
extract or retire | transplant useful delta to current main |
orphan-no-unique-commits |
retirement | retire after dependency/reference check |
orphan-clean-ahead |
extract or retire | normal PR or clean replacement |
orphan-diverged |
extract or retire | clean current-main replacement |
unknown |
hold | manual classification |
For every row:
direct_branch_merge_allowed = false
Read:
main SHA;Record a snapshot identifier:
S = SHA256(main_sha || sorted(branch_head_shas) || open_pr_heads)
The exact formula may be implemented later; the conceptual requirement is that merge decisions are bound to one live snapshot.
Run the existing branch convergence auditor.
Every non-main branch must receive one known state. Unknown/inconsistent states fail closed.
Immediately exclude from the merge queue:
These move to RETIRE, PRESERVE_EVIDENCE, or HOLD.
For every responsibility with more than one surviving branch:
main;Never solve duplication by merging competing implementations together unless the PR explicitly reconciles them and reviewers understand that combined design.
For closed-unmerged-unique-work, orphan-diverged, and relevant post-merge-branch-moved branches:
old branch
-> inspect exact unique commits/files/hunks
-> compare with current canonical contracts
-> discard obsolete parts
-> preserve still-useful semantics
-> new clean branch from current main
-> bounded PR
-> fresh CI/evidence
This is semantic transplantation, not ancestry preservation.
Use cherry-pick only when the commit is demonstrably self-contained and compatible with current contracts. Otherwise reconstruct the minimal delta.
Let P be all open, non-draft, non-superseded PRs plus replacement PRs created in Step 4.
Construct dependency DAG G=(P,E).
A PR with nonzero indegree cannot be first in the merge queue.
If cycles exist:
cycle -> HOLD
Then either:
For candidate PR p:
MergeEligible(p) =
p.open
AND NOT p.draft
AND p.head_is_exactly_expected
AND p.not_superseded
AND p.diff_is_bounded_and_understood
AND p.dependencies_are_integrated_or_explicitly_independent
AND p.required_checks_are_green_for_exact_head
AND p.evidence_is_current_for_exact_head
AND p.required_independent_review_is_satisfied
AND p.authority_invariants_are_satisfied
AND p.base_was_revalidated_after_previous_merge
If any term is false or unknown:
MergeEligible(p) = false
Unknown is not optimistic success.
Risk class influences review/evidence requirements, not whether safety can be bypassed.
Suggested classes:
Examples:
Minimum: bounded diff, current links/facts, green applicable checks, normal integration decision.
Examples:
Require code/test review and current exact-head CI.
Examples:
Require stronger exact-head evidence and independent review according to the affected contract.
Examples:
pull_request_target;Require explicit threat review, least privilege, fail-closed behavior, pinned dependencies where relevant, and independent integration control.
Only after Step 6 yields true may priority be considered.
Use lexicographic priority rather than a compensating weighted sum:
Priority(p) = lexicographic(
critical_path_class,
dependency_unlock_count,
conflict/staleness_reduction,
cleanup_gain,
negative_review_cost
)
Recommended criticality order:
P0 security / integration safety blockers
P1 canonical product critical path
P2 branch/contract convergence and dependency unlocks
P3 community/growth infrastructure
P4 research/docs leaves
Within the same class prefer the PR that:
Do not prioritize merely because a branch is old.
Immediately before merge:
expected_head_sha;If the expected head changed, abort.
After merge p creates new main=M':
old plan = invalid
Rerun from Step 0.
Never continue merging from a queue computed against the old main without revalidation.
After integration, a source branch becomes cleanup eligible only when:
Physical deletion is a repository-administration operation separate from merge correctness.
Repository owner should enable:
Settings -> General -> Pull Requests -> Automatically delete head branches
after confirming this matches desired evidence retention practice.
More importantly, protect main under issue #35 before increasing autonomous integration authority.
repeat:
S <- live repository snapshot
A <- branch_convergence_audit(S)
P <- build_branch_merge_plan(A)
classify every branch into:
integration-review
extract-or-retire
evidence-preservation
hold
retirement
for every stale unique branch:
if useful semantics remain:
create clean current-main replacement PR
else:
mark retire
G <- dependency DAG of active integration PRs
Ready <- {
p in G
where indegree(p) == 0
and MergeEligible(p) == true
}
if Ready is empty:
publish blockers/preparation/retirement plan
stop
p <- lexicographically highest-priority member of Ready
external reviewer/maintainer makes integration decision
if accepted:
merge p using expected_head_sha
preserve merge/evidence record
continue # MUST resnapshot; old queue is invalid
else:
record hold/rejection/supersession evidence
continue or stop based on new state
The planner itself never supplies the external reviewer/maintainer makes integration decision step.
The exact wave membership is recomputed continuously, but the present structure is:
main remains publicly unprotected.State observed: open, non-draft.
Action:
PR integration-review candidate
It should be evaluated against exact-head CI, diff scope, dependency compatibility, and normal review requirements. This document does not pre-authorize its merge.
State observed: draft.
Action:
HOLD
Its own activation/security review must complete before it enters integration review. Merge must not be used to bypass the explicit opt-in/protected-main boundary.
State observed: draft.
Action:
HOLD
Its exact-head runtime evidence exists, but a genuinely separate human/reviewer witness is still an explicit required gate. Branch hygiene cannot substitute for that witness.
Use the planner/auditor output to inspect extract-or-retire branches by semantic responsibility.
Priority within this wave:
Every rescued item becomes a new current-main PR. The old branch itself is not merged.
Preserve durable receipts, negative evidence, run IDs, exact SHAs, and conversation records. Then retire refs whose names are no longer required.
Delete exact revalidated:
Then rerun the audit and measure reduced ambiguity.
BranchAmbiguity =
unresolved_unique_stale
+ unknown
+ ambiguous_open_prs
+ post_merge_moved_unclassified
Target: trend toward zero.
IntegrationYield =
verified durable changes integrated
-----------------------------------
reviewer effort + conflict debt + rework
High merge count alone is not success.
CleanupRatio = retired_cleanup_safe_refs / cleanup_safe_refs_identified
This measures hygiene, not project value.
EvidenceRetention =
retired evidence refs with durable evidence elsewhere
----------------------------------------------------
retired evidence refs
Target: 1.0.
One simple diagnostic is:
StaleUniqueLoad = sum(risk_weight(b) * max(1, behind_by(b)))
for stale branches with unique work.
This is prioritization evidence only; it cannot override merge gates.
Failure: obsolete schemas/runtime/security assumptions re-enter main.
Prevention: stale refs must be semantically extracted onto current main.
Failure: already-reviewed work is merged again because ancestry still appears divergent.
Prevention: merged PR head identity outranks ancestry for cleanup classification.
Failure: old runtime/verification evidence is cited for changed code.
Prevention: exact-head evidence binding.
Failure: the system that proposes a change also interprets its own green run as approval and merges itself.
Prevention: planner always emits merge_authorized=false; independent integration decision remains external.
Failure: merge/close count is optimized instead of useful canonical state.
Prevention: hard gates plus IntegrationYield/ambiguity metrics.
Failure: evidence and useful work are deleted simply to make the branch number smaller.
Prevention: preserve/extract before retire.
Failure: five PRs are approved against one main; the first merge invalidates assumptions for the next four.
Prevention: recompute after every merge.
tools/branch_merge_planner.py consumes the JSON produced by tools/branch_convergence_audit.py and emits:
It deliberately cannot emit final merge authorization.
The existing Branch Convergence Audit workflow runs both tools so there is one canonical read-only maintenance surface rather than parallel branch-management workflows.
This branch-convergence program is successful when:
main is the only canonical code state;main before stronger autonomous integration behavior;A comprehensive branch-to-main algorithm makes the repository legible to human contributors and future agents. A newcomer should be able to answer, from public evidence, whether a branch is canonical, actively reviewable, blocked, evidentiary, superseded, awaiting extraction, or safe to retire. That lowers coordination cost without weakening the verification-first boundary.