+| `auto_merge.merge_train.enabled` | `true` | **Settings → Auto-merge → Merge train → Conflict-aware merge train.** Conflict-aware merge train in every automerge lane (hive, trusted-author, contributor) ([#15117](https://github.com/hivecommons/hive/issues/15117)). Each sweep groups the open approved / mergeable-pending PRs of one repo+base by overlapping changed files (`GET /pulls/{n}/files`, cached per head SHA) and lets ONE front per group merge — ordered readiness first: a head the lane last saw at the merge gate (green, approved, soaking or waiting on a sweep) leads, one it has not evaluated since its push comes next, one still at CI / Review trails, then clean-mergeable before behind, then oldest; recomputed every pass, so a member that turns green moves up and one that turns red moves back — while the others wait at stage/080 with lane reason `merge-train:queued-behind#<front>:<pos>/<size>:…` (tracker pill "In merge queue · 3 of 4 · ~4m", never a human stage, never `needs-rebase` as a human flag). The moment the front merges, every sibling whose branch is merely `behind` gets `PUT /pulls/{n}/update-branch`; a `dirty` one is handed to the fixer's rebase-resolve episode (`requested_by: merge-train`, the shared two-attempt guard of [#15104](https://github.com/hivecommons/hive/pull/15104); the fixer router still requires a head the hive can push to, so a fork without maintainer edits stays on the plain `conflicting` path for a person). A dependency bot's branch (`renovate/*` head ref, or a Renovate, Dependabot or Mergeraptor author) gets neither — behind or dirty, sibling or front, the bot rebases it itself (projectbluefin/utah#1097). A head the lane last saw blocked on its own (red required check, terminal hold, permanent merge refusal) never fronts, and a group whose best member is blocked imposes no ordering (fail-open) — nobody waits behind a PR that is not moving. One INFO line `merge train` per order change, not per cycle. The queue carries one PR per issue: when two open PRs declare the same `Fixes #N`, the sweep keeps one and holds the other with lane reason `merge-train:duplicate-of#<winner>:<issue>/0:0/0:` (tracker pill "Duplicate of #15402 · needs a pick"; *Let hive decide* supersedes, [#15395](https://github.com/hivecommons/hive/issues/15395)). That pick sees one lane; when the two claimants sit in different lanes (the hive's own PR and a trusted human's PR for one issue) every lane holds its candidate with lane reason `merge-train:claim-conflict#<other>:<issue>/0:0/0:` and the log line `same-issue claim conflict undecided: #A vs #B`, so neither is admitted until a decision is recorded on one head or the other PR closes — the PR parks at 085, the chevron reads "held · duplicate of #B · needs decision", and the row's options name the concrete PRs; the hive recommends and never picks ([#15810](https://github.com/hivecommons/hive/issues/15810)). Both rules hold only heads at the merge gate ([#17439](https://github.com/hivecommons/hive/issues/17439)): a same-issue PR still running CI or awaiting review is evaluated as usual (its row reads CI / Review) and is held at the merge point only if it gets there; the first PR at the merge point keeps the issue (among several already at the gate: green first, then the earlier-opened), and the pick stands until that PR closes or is blocked for good — a check going red mid-run does not flip it. `false` restores independent per-PR evaluation. A PR GitHub reports conflicting on its own, or one at stage/072 returned-to-contributor (label or stage record), is never a member nor counted in the train's size and draws no train idle comment; a conflicting PR rides only while the train itself is repairing it (its rebase requested behind a merged front, loop guard not spent) ([#15395](https://github.com/hivecommons/hive/issues/15395)). |
0 commit comments