/merge-train — Merge What's Proven, Report the Rest
"Safe to merge" is a claim, and claims need receipts. This skill reduces the claim to five mechanical facts and merges only where all five hold. A held PR is not a failure — its reason line tells a human exactly what to supply (a review, a label, a green run). No judgment happens at merge time; the judgment was banked here once.
The five facts (all must hold)
- CI green — every status check concluded SUCCESS/NEUTRAL/SKIPPED.
- Approved — review decision is APPROVED, or an evidence-backed
adversarial-review:passedlabel (step 2b). - Mergeable — no conflicts with the target branch.
- Autonomy label — the PR carries
autonomy:green, applied by a human. The label IS the standing approval; the model executing this skill never applies it. - Overrides acknowledged — any
JUDGMENT-OVERRIDE:marker in the PR body is matched by anoverride-ackedlabel.
Invocation
/merge-train # dry-run: SAFE/HELD report, no merges
/merge-train --execute # merge the SAFE set, base-first
Procedure
- Enumerate open PRs (GitHub:
python3 scripts/merge_train.pyships the whole check; other forges: gather the same five facts via their CLI/API). No forge access → every PR is UNVERIFIED, reported as such — never assumed safe. - Classify each PR SAFE or HELD; a HELD PR lists every missing fact.
2b. Adversarial review — the review a bot can't do. Read the diff trying
to find a reason it must NOT merge, framing it as an external
contributor's. Findings carry file:line evidence; post them, or
"adversarial pass: no blocking findings — checked ", as a PR
comment. Run it on any substantive PR (behaviour-changing; docs, lockfile
bumps, generated files and pure formatting are exempt) — measured at ~15%
overhead for two fabrications CI structurally could not see.
- It does not replace fact 2. A PR whose review bot silently never ran
may substitute the label
adversarial-review:passed, and that label counts ONLY when a comment backs it —merge_train.pyholds a labelled PR that has no evidence comment. The one route to SAFE without a real approval is the one route that must not be self-asserting. - Blocking findings → fix first. The label is never applied over open findings.
- It does not replace fact 2. A PR whose review bot silently never ran
may substitute the label
- On
--execute: merge the SAFE set in base-first order (PRs targeting the default branch before stacked PRs). A merge failure stops the train. - Verify after: target-branch CI still green.
- End with ONE verdict line and log it to the ledger:
MERGE-TRAIN: <n> merged (#ids) | <m> HELD (<top missing fact>) | <k> UNVERIFIED | target CI: green|red
Rules
- Never widen the safe set inline. "That red check is flaky" is a judgment call — the PR waits for a human, or the check gets fixed. Loosening the five facts is a one-way-door decision (/door), not an edit.
- HELD and UNVERIFIED are never silently upgraded.
Composes with
/refute— how a PR earns its evidence before approval./gate— the five facts are a standing gate; the ledger line is its record./verdict—MERGE-TRAIN:lines land in the append-only ledger, so the next train diffs against the last.