Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions docs/initiatives/auto-rebase-vs-merge-queue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# Initiative: Auto-rebase Fan-out Reduction — Decision Record & Merge Queue Go/No-Go Gate

**Status:** Decision record — free mitigation validated (≥50% metric met); Merge Queue go/no-go **deferred to a human** (epic [#736](https://github.com/petry-projects/.github-private/issues/736) open question)
**Author:** dev-lead / Claude Code
**Date:** 2026-06-21
**Scope (confirmed):** Records the measured before/after impact of the **review-ready auto-rebase
fan-out restriction** (the free, plan-independent mitigation from epic [#736](https://github.com/petry-projects/.github-private/issues/736),
Story [#738](https://github.com/petry-projects/.github-private/issues/738)) and the now-measurable
agentic-conflict-resolution rate (Story [#737](https://github.com/petry-projects/.github-private/issues/737)).
Defines the GitHub **Merge Queue** go/no-go as explicit, checkable gate conditions. Does **not** decide
the go/no-go — that remains a human call (see §4).
**Constraints (confirmed):** Docs-only. The before/after numbers are sourced from the Story 1 (#737)
observability report and the discussion [#735](https://github.com/petry-projects/.github-private/discussions/735)
manual baseline — not re-estimated here. Fan-out volume is an **estimate** (per-run behind-PR counts
live in the central reusable, not this repo); it is labelled as such throughout, consistent with the
Story 1 report's method note.

---

## 1. What was changed, and why

Branch protection's "Require branches to be up to date" serializes merges: every merge to `main` leaves
all other open PRs behind. The `Auto-rebase non-Dependabot PRs` workflow papered over that by calling
`update-branch` on **every** behind non-Dependabot PR on every push to `main` — fanning a fresh CI run
onto each. At the repo's measured throughput (~12.3 merges/day, ~14–18 concurrently-open PRs) that was
an estimated **~170–220 redundant branch-update CI runs/day** (discussion #735), the bulk of which were
re-staled by the next merge before any human looked at them.

Epic #736 split the response into two tiers:

1. **Free, plan-independent mitigation (Story #738):** stop fanning out to PRs nobody will review —
restrict the update to a **review-ready eligibility predicate**. Landed **2026-06-15** in the central
reusable via PR [petry-projects/.github#468](https://github.com/petry-projects/.github/pull/468)
(issue #465). Predicate: **non-draft AND (current `APPROVED` review OR `auto-rebase:ready` label)**,
tunable via an `eligibility` workflow input. The merge-method update (approval-safe) and the
`<!-- auto-rebase-conflict:` sentinel → dev-lead agentic-rebase path are both preserved.
2. **Plan-gated follow-on (this record's gate, §4):** GitHub Merge Queue — evaluated **from data**, not
speculation, and explicitly **not decided here**.

Before the plan-gated trade could even be weighed, the agentic-conflict-resolution frequency had to be
counted — and the owner could not, because the trigger is an un-indexed HTML-comment sentinel
(discussion #735). Story #737 instrumented exactly that (`scripts/auto_rebase_health.sh` +
`auto-rebase-health.yml`).

---

## 2. Measured fan-out reduction (AC #1)

The directly comparable measure is the **behind-PR multiplier** — the count of PRs the fan-out updates
per push to `main`. The auto-rebase **run count** (driven by pushes to `main`) is unchanged by the
restriction, so reducing the multiplier reduces the branch-update CI volume proportionally.

| Metric | Before (all behind non-Dependabot PRs) | After (review-ready only) | Source |
|---|---|---|---|
| Behind-PR multiplier (PRs updated per push) | 13 of 13 open non-Dependabot PRs | **3 of 7** eligible | #737 report (14-day smoke) → #738 post-change (6-day) |
| Multiplier reduction | — | **~57%** | 7 → 3 |
| Est. branch-update CI runs/day | ~170–220 (manual) · ~116 (instrumented) | proportionally **~57% lower** | #735 baseline · #737 report |
| Merge throughput | ~12.3 merges/day (peaks 16–21) | unchanged (not a target) | #735 |
| Time-to-merge | median 5h · mean 31h · p90 71h · max 629h | not re-measured in this record | #735 |

> **Fan-out is an estimate.** Per-run behind-PR counts are not logged in this repo (the `update-branch`
> calls live in the central reusable), so re-runs = auto-rebase runs × eligible-PR count. The reduction
> is reported as the **eligible-PR multiplier** drop (7 → 3 = ~57%), which the restriction controls
> directly; the absolute CI-runs/day figures carry the #735/#737 estimate caveat.

### Success-metric verdict

Epic #736's success metric: **auto-rebase-triggered branch-update CI runs drop by ≥ 50%** from the
~170–220/day baseline.

**✅ MET.** The review-ready restriction cut the behind-PR multiplier by **~57%** (7 eligible → 3),
clearing the ≥50% bar, with **no plan upgrade** and **without losing** the agentic conflict-resolution
fallback (the sentinel path is preserved — see §3).

---

## 3. Measured agentic-conflict-resolution rate (AC #2)

This is the number the owner could not previously count. It is now published by the Story #737 report
(`scripts/auto_rebase_health.sh`), which scans the un-indexed HTML-comment markers directly: conflict
sentinels (`<!-- auto-rebase-conflict:`) vs. dev-lead `rebase` terminal markers
(`intent=rebase status=…`, with the `status=applied` subset = sentinels dev-lead actually resolved &
force-pushed).

| Window | Sentinels fired | Dev-lead `rebase` responses (resolution rate) | `status=applied` (applied rate) |
|---|---|---|---|
| **Before** — #737 14-day smoke (~2026-06-01 → 06-15) | 161 (**~80 / week**) | 74 — **46%** (**~37 / week**) | 0 — **0%** |
| **After** — #738 6-day post-change (~2026-06-15 → 06-21) | ~13 (**~15 / week**) | 7 — **54%** | 2 — **15%** |

**Reading the rate.** The agentic resolver *responds* to roughly half of conflict sentinels, but the
**applied** rate is low (0% then 15%): in the 14-day window every resolved rebase terminated
`no-changes` — i.e. the agentic rebase produced no commit to force-push. That is genuine telemetry, not
a bug, and it is **load-bearing for the §4 gate**: a low real-resolution (applied) rate means relatively
little unique work would be lost by dropping the agentic path for Merge Queue. The numbers are still
small-sample (single-digit applied counts); the gate below treats the threshold as something to agree
on against a longer window, not to read off one 6-day sample.

---

## 4. Merge Queue go/no-go gate (AC #3) — conditions only, **decision deferred**

GitHub Merge Queue is the plan-gated follow-on. This record defines **when** it would be worth adopting
as explicit, checkable conditions. It does **not** make the call: the actual go/no-go is a human
billing + product decision, surfaced as the **epic #736 open question** ("is leadership willing to make
that trade?"), and is **not asserted resolved here**.

### Gate conditions (all must hold for a "go")

| # | Condition | Checkable signal | Current reading |
|---|---|---|---|
| G1 | **Plan eligibility** — Merge Queue is available on this repo's plan | Repo plan / settings expose Merge Queue | **Satisfied** — per the epic #736 owner resolution (open question #1), Merge Queue **is** available on this plan (private repo); the discussion #735 "private repo → Team/Enterprise required" concern does **not** apply here. Eligibility uncertainty is removed; the *adoption* decision stays open. |
| G2 | **Throughput sustained above the "consider Merge Queue" threshold** (≥10 merges/day) | #735 / #737 throughput | **Satisfied** — ~12.3 merges/day, peaks 16–21. |
| G3 | **Agentic-conflict-resolution value below an agreed threshold** — because Merge Queue **drops** the sentinel → dev-lead rebase path and proactive background branch updates | #737 report `status=applied` rate over a ≥4-week window vs. an agreed ceiling (e.g. applied-rebases/week the team is willing to convert to manual resolution) | **Threshold not yet agreed.** Current signal is *favourable* to a switch (applied rate 0%→15%, most rebases `no-changes`), but it is small-sample; needs a longer window and a human-set ceiling before it counts as met. |
| G4 | **The documented trade-offs are accepted by a human** | Sign-off referencing the #735 comparison table | **Open** — losing agentic conflict resolution (→ manual), losing proactive background branch updates, and adding a `merge_group` CI trigger are accepted trade-offs only by explicit human decision. |

**Net.** G1 and G2 are satisfied; G3 is *trending* toward met but needs an agreed threshold over a
longer window; G4 is an explicit human sign-off. **No go/no-go is recorded here.** When the team is
ready, resolve the epic #736 open question against these conditions — the data to check G2 and G3 is now
produced continuously by the #737 report.

### What a "go" would mean operationally (for reference, not a decision)

- **Add** a `merge_group` CI trigger and make the merge-queue check required (the only CI change).
- **Retire or scope down** the auto-rebase fan-out (Merge Queue tests the synthetic `merge_group`, so
per-PR branch-updates become redundant for queued PRs) — note auto-rebase and Merge Queue solve
*adjacent* phases (keeping open PRs current vs. serializing the merge), so the team may keep a
narrowed auto-rebase running alongside.
- **Accept** manual conflict resolution in place of the agentic sentinel path (the §3 applied rate is
the cost estimate for this).

---

## 5. References

- Epic [#736](https://github.com/petry-projects/.github-private/issues/736) — fan-out reduction +
conflict-rate instrumentation; success metric (≥50% fan-out reduction) and the Merge Queue open
question.
- Story [#737](https://github.com/petry-projects/.github-private/issues/737) — auto-rebase
instrumentation (`scripts/auto_rebase_health.sh`, `.github/workflows/auto-rebase-health.yml`); source
of the before-numbers and the conflict-resolution rate.
- Story [#738](https://github.com/petry-projects/.github-private/issues/738) — review-ready fan-out
restriction; delivered as central PR
[petry-projects/.github#468](https://github.com/petry-projects/.github/pull/468) (issue #465); source
of the after-numbers.
- Discussion [#735](https://github.com/petry-projects/.github-private/discussions/735) — manual baseline
(~170–220 redundant CI runs/day, ~12.3 merges/day, TTM mean 31h / p90 71h) and the auto-rebase vs.
Merge Queue comparison table.
- `docs/initiatives/agentic-release-strategy.md`, `docs/initiatives/mcp-powered-review.md` —
initiative-doc header shape.
Loading