Merge pull request 'Design 47: a move of the trunk asks every active check again (ADR 0395)' (#381) from design/47-recheck-on-trunk-move into main

This commit was merged in pull request #381.
This commit is contained in:
2026-10-16 17:35:52 +00:00
@@ -4,6 +4,7 @@ status: in-progress
code: [mesh-controller, mesh-catalog modules/mesh-delivery]
updated: 2026-10-16
decisions:
- "ADR 0395"
- "ADR 0382"
- "ADR 0350"
- "ADR 0335"
@@ -103,7 +104,9 @@ allows.
at the moment the build seat clones it, the **trunk commit**, and the verdict names both. When another merge
moves the trunk, a `ready` delivery goes back to `proposed` on the observed event `trunk moved`, with both
commits in the transition's reason; a `rejected` one stays `rejected`, its statuses saying the verdict is out
of date. Nothing is asked for it: a recheck, a new head or the merge tool asks the check again. The row from
of date. The move itself asks the check again of every active open pull request into that trunk that merges
cleanly (ADR 0395, *A move of the trunk asks every check again* below); a recheck, a new head or the merge tool
asks it too. The row from
`proposed` to `checked` takes only a verdict that names the trunk's head as its trunk commit, so a verdict for
an older trunk is kept and shown and does not count, and the rows reach a fixed point. Checked by
mesh-delivery's `TestATrunkMoveSendsAReadyDeliveryBackToProposed` and the table's own rollout.
@@ -124,7 +127,7 @@ What this leaves as it is, said so nobody reads more into it:
- **A check that was asked and never answers** is listed by `stalled` an hour after the ask, and is asked again
with `mesh-delivery.recheck`, which the merge tool's refusal names.
The transitions are those of ADR 0239 decision 2, ADR 0270 and ADR 0323. A delivery that is
The transitions are those of ADR 0239 decision 2, ADR 0270, ADR 0323 and ADR 0395. A delivery that is
merged while not `ready` goes to `held`. Its check did not pass, and only a person decides that it goes on. A
delivery merged with no rollout answering it within ten minutes is held too, with the true reason, and listed by
`stalled` at once. Nothing waits silently.
@@ -389,6 +392,34 @@ only once it is built.
A group's state is derived from its members and its composed check, and is shown, never stored apart from
them.
## A move of the trunk asks every check again
*ADR 0395, changing ADR 0323 §4.* When the forge's holder hears a repository's trunk move, mesh-delivery asks the
check of every active open pull request into that trunk against its new head at once, so a verdict is current by
the time anyone looks.
- **A conflict is told, not checked.** Before asking a check, mesh-delivery asks the forge whether the head merges
cleanly into the new head, which needs no builder. When it does not, no check is asked: its statuses fail naming the trunk commit and the files in
conflict where the forge gives them, and it is told once on the pull request, not again while the same conflict
stands. Every later trunk move and its next push ask the forge again; once it merges cleanly its check is asked.
- **One check per pull request.** When a check against a newer trunk commit is asked for a pull request, its check
against an older trunk commit is dropped if it waits and ended if it runs, said in the build log and on the
queue, as a new head already ends its old head's check (issue 726). An ended check delivers no verdict, so none of its builds is reused (ADR 0350 §7 keeps only builds a verdict
names); its scratch records wait for ADR 0350 §5's seven-day sweep. A try and a delivery's build are never touched.
- **The queue's order.** Delivery builds first; then checks of pull requests marked ready; then the rest, the most
recently pushed first.
- **Inactive pull requests are left out.** One with no push and no ready mark for 7 days is not asked again on a
trunk move; its statuses say out of date and that a push, a ready mark or a recheck asks its check. A recheck
takes a delivery that is still proposed and whose verdict is out of date, and asks its check (issue 888).
- **Groups.** For a group's members a move asks only each member's own check; the group's composed check runs again
through those rechecks (ADR 0323 §6) and is never asked by the move itself. A move made by a member merging in
the group's order asks the other members nothing, since they merge moments later; their verdicts are out of date
until then, and one that does not merge is asked again at the next move, its next push or a recheck.
**Its cost** is at most one check asked per active, cleanly merging pull request per trunk move: about 550 a day at
ADR 0323's measured load, fewer once conflicting and inactive ones are left out; ending an older check saves builder
time, not checks asked. Issue 944 measures it once built.
## What every transition does
In this order, each by its owner:
@@ -420,7 +451,7 @@ In this order, each by its owner:
| `what-if` | the delivery plan a diffset would have, asked of the controller's planner, kept nowhere |
| `table` | the state table and the machine-step table, with bounds and H2's repairs |
| `stalled` | every delivery held past its bound, with the transition H2 may take, and every waiting rollout no live delivery holds |
| `recheck` | a rejected or ready delivery back to proposed, with why |
| `recheck` | a rejected or ready delivery back to proposed, with why; a delivery still proposed whose verdict is out of date has its check asked (ADR 0395) |
| `release` | a held delivery to delivering, with why: a person's word |
| `stop` | any delivery not final to stopped, with why; its rollout is ended through the controller. On a rollout that carries other deliveries it first answers what ending the rollout would take down, and acts on `way`: `again` or `walk` (ADR 0299) |
| `close` | H2's only verb: the transition the table names for a stalled delivery, refused otherwise |