diff --git a/00-META/glossary.md b/00-META/glossary.md index 04bd1286..cf622668 100644 --- a/00-META/glossary.md +++ b/00-META/glossary.md @@ -305,13 +305,17 @@ and the operator act. **Recorded by** the controller's `identity` and `licences` **Purpose.** To take one commit from its pull request to every node that should run it, and to put it back when it fails. **Recorded by** the `mesh-delivery` module (deliveries) and the controller (the planner, the walk). **Downstream of** Module, Core, Health and repair and Data. -**Decided by** ADR 0162, 0218, 0236, 0237, 0238, 0239, 0250, 0267, 0270, 0276. +**Decided by** ADR 0162, 0218, 0236, 0237, 0238, 0239, 0250, 0267, 0270, 0276, 0323. **Uses:** module, node, declaration and send (Placement), health (Health and repair), person. - **merge check** — the two statuses a pull request carries before it may merge: the **merge gate** (`mesh/merge-gate`, the build seat's composed check of the modules the change touches) and the **repository check** (`mesh/repo-check`, the repository's own `merge-check.sh`) - (ADR 0238). + (ADR 0238). Both judge the merge of the pull request's head into a named **trunk commit**, made in the + build seat's own clone and never pushed (ADR 0323). +- **trunk commit** — the commit of the trunk a merge check's verdict was judged against: the trunk's head when + the build seat cloned it. The verdict holds for that commit only, and goes out of date when the trunk moves + (ADR 0323). - **build seat** — the seat whose holder builds modules, `node-build-agent`; its holder on a node is the **builder**. Any node may hold the seat, so there is no build node by nature (ADR 0237). diff --git a/03-DESIGN/01-to-be/45-a-core-that-cannot-fail-silently.md b/03-DESIGN/01-to-be/45-a-core-that-cannot-fail-silently.md index e762ae39..769c2c79 100644 --- a/03-DESIGN/01-to-be/45-a-core-that-cannot-fail-silently.md +++ b/03-DESIGN/01-to-be/45-a-core-that-cannot-fail-silently.md @@ -4,6 +4,7 @@ status: in-progress code: [mesh-controller, mesh-host, mesh-tools, mesh-catalog, mesh-sdk, mesh-lab] updated: 2026-10-12 decisions: + - "ADR 0323" - "ADR 0314" - "ADR 0293" - "ADR 0289" @@ -677,6 +678,19 @@ what is not an ordinary send, and the verdict — posted on the pull request. Th a state machine, kept, followed by the release and written to the commit as a note; which parts are built is Phase 5's. +Revision, ADR 0323 (2026-10-12). **The gate judges what merging makes, not the head.** The build seat takes +the trunk the pull request merges into, its head at that moment as the check's **trunk commit**, and makes in +its own clone the merge of the head into it, as the forge's default merge would; both layers judge that +merge, and a head that does not merge cleanly fails, naming the files in conflict. The merge is only checked: +never pushed, never registered. The verdict names the head and the trunk commit in both statuses' words +("head … merged into trunk …"), in mesh-delivery's `checks` and `show` and in the kept delivery plan, and +names the commits of the other repositories the check read; their move is issue 568's question. When the +trunk moves, the forge's holder puts both statuses of every open pull request into it back to pending with +the reason and runs nothing; the merge tool refuses a verdict whose trunk commit is not the trunk's head, +asks that head's check once, says how long the last check of the repository took, and never merges by +itself (checked by the builder's `TestReplay341`, replayed as R341, and the forge module's `trunk` and +`guard` tests). + **The replays.** mesh-lab carries a scripted scenario for each core incident, asserting the rule's outcome, run on every merge to mesh-controller, `mesh-host` and mesh-tools: diff --git a/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md b/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md index c741eda0..8e7be134 100644 --- a/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md +++ b/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md @@ -4,6 +4,7 @@ status: in-progress code: [mesh-controller, mesh-catalog modules/mesh-delivery] updated: 2026-10-12 decisions: + - "ADR 0323" - "ADR 0313" - "ADR 0306" - "ADR 0299" @@ -81,7 +82,7 @@ allows. | State | Means | Bound | H2 after the bound | |---|---|---|---| -| proposed | a head was announced and is being checked | 1 hour | nothing: the check's own watchdog (S6) speaks | +| proposed | a head was announced and is being checked | 1 hour from when its check is asked; none while its verdict is out of date and no check is asked | nothing: the check's own watchdog (S6) speaks | | checked | a verdict arrived | 1 minute | nothing: it is decided at once | | ready | it passed; it waits to be merged | none | — | | rejected | it failed its check | none | — | @@ -90,7 +91,32 @@ allows. | delivering | its walk runs; its builds are asked and registered tier by tier | 2 hours | `delivered`, `failed` or `superseded`, as the walk's record says | | delivered, failed, superseded, stopped, retired, covered | final | — | — | -The transitions are those of ADR 0239 decision 2 and ADR 0270. A delivery that is +**A verdict holds for one trunk commit** (ADR 0323). The check judges the head merged into the trunk's head +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 +`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 walk. + +What this leaves as it is, said so nobody reads more into it: + +- **mesh-delivery's trunk head is the last merge it heard** into that trunk while the delivery was open. A push + to the trunk that is not a merge it hears does not move it; the forge's holder, which reads the branch, and + the merge tool, which compares commits when asked, still catch it. +- **A verdict that names no trunk commit**, from a build seat older than ADR 0323, counts in mesh-delivery as it + did: such a delivery stays `ready`. The forge reads the same verdict out of date once its trunk moves, and the + merge tool refuses it and asks the check. The two agree once the head is judged again. +- **A verdict no build judges** (a change that touches no module, in a repository with no `merge-check.sh` or + not the mesh's) names the base branch's head the forge announced with the head as its trunk commit. +- **In a busy repository the merge tool can refuse, ask, and refuse again**: another merge may move the trunk + while the asked check runs, and the new verdict is then out of date too. Each refusal asks once more; the + merge goes through once a check finishes before the next merge. +- **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 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 walk answering it within ten minutes is held too, with the true reason, and listed by `stalled` at once. Nothing waits silently. @@ -308,9 +334,15 @@ only once it is built. first, then *built by* and *version skew*, then *engine before controller*. The pair shows the rule that won and the rules it won over. Rules of one rank both ways are a contradiction. The group is `rejected`, and the reason names both members, both rules and the `after:` line that would settle it. -- **Check**: the members' heads composed together, one gate over every machine with all their definitions. It - is asked by mesh-delivery through `delivery-check` when the group forms or a member's head moves, and - posted on every member's head as `mesh/delivery-group`. +- **Check**: the members' heads composed together, one gate over every machine with all their definitions, + each head merged into its own trunk's head first and named with that trunk commit (ADR 0323). It is asked + by mesh-delivery through `delivery-check` when the group forms or a member's head moves, and posted on + every member's head as `mesh/delivery-group`. A member rebased or pushed is a new head with its own check: + it takes its old head's place in the group, even once the group is delivering, and the composed check runs + again for the new heads instead of holding the group. A merge into a member's trunk that is not one of the + group's members puts the composed check out of date: the group reads `checking` with the reason, and the + composed check runs again once a member is judged again. Checked by mesh-delivery's + `TestAGroupsComposedCheckGoesOutOfDateOnAMergeThatIsNotItsMember` and `TestARebasedMemberIsComposedAgainNotHeld`. - **Delivering**: in order. A member waits in `published` until the one before is `delivered` or `covered`. A member published while its group's composed check is asked and not answered waits there for the answer; one held because that check had not passed is *lifted* back to `published` once it passes or warns for the