Files
hq/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md
T
jochen cbd9f092d8
mesh/merge-gate pass: the change touches no module of the mesh's graph
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
ADR 0270 and 0271 accepted: their home in designs 47 and 45, and the glossary's final states
The operator accepted both on 2026-10-09. Design 47's state table gains covered and what ends a held
delivery by itself, and its group the wait for a composed check and the lift; design 45's signals table
gains S17 and its planned bus step says the wait is told at once. The glossary's delivery entry names its
six final states.
2026-10-09 09:24:30 +02:00

16 KiB

layer, status, code, updated, decisions
layer status code updated decisions
to-be designed
2026-10-09
02-DECISIONS/0270-a-held-delivery-that-moves-nothing-or-that-a-later-delivered-merge-contains-ends-by-itself-and-a-hold-whose-reason-is-gone-lifts.md
02-DECISIONS/0250-a-merge-heard-only-from-the-buss-history-is-retired-and-owed-work-the-forge-cannot-do-ends.md
02-DECISIONS/0249-a-delivery-groups-order-rules-have-a-precedence-and-a-declared-order-outranks-them-all.md
02-DECISIONS/0239-a-delivery-is-owned-by-the-mesh-delivery-module-and-runs-from-commit-to-delivered.md
02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md
02-DECISIONS/0236-a-build-is-judged-on-its-first-machine-and-put-back-by-something-other-than-itself-and-so-it-rolls-out-unattended.md
02-DECISIONS/0201-a-module-keeps-its-current-state-in-key-value-buckets-it-declares-and-reaches-through-the-runtime.md

47 — Delivery: from a commit to delivered

A delivery is one commit in one repository, from the moment its pull request's head is announced to the moment every machine of its deploy plan runs it, or to the moment it fails, is superseded or is stopped. A delivery group is two or more deliveries that share a head branch name, delivered as one unit in order. Both are owned by one module, mesh-delivery, which records every step and asks the controller for each act. (ADR 0239.)

This is the delivery of to-be 10 carried out. To-be 10 says what is built: the comparison of source and artifacts decides, and nothing here changes that. This design says who answers for one commit's journey and in what order the steps are allowed.

The parts

 forge's holder ──pull.updated / .merged / .closed──►  mesh-delivery  ◄──checked / plan-moved──  controller
   (statuses, the view,                               (deliveries, groups,                    (planner, gate,
    the notes)                                          the table, its state)                  registration,
        ▲                                                 │            │                       sending, walk)
        └── its tools: note, view, status ◄───────────────┘            └── its verbs: delivery-plan, -order,
                                                                            -check, deliver, delivery-stop,
                                                                            delivery-walks
  • The controller stays the only writer of what it owns: machine declarations, bus objects, grants, registration. It keeps the primitives: the planner (one function, ADR 0238 decision 3), the gate, the trunk rule, a gated send, the rollback and the walk of one trunk commit's tiers across machines. It still answers every pull request's head with its check itself, so a check never depends on mesh-delivery.
  • mesh-delivery is a Go bundle holding the mesh-scoped seat mesh-delivery. It owns the delivery, the group, the state table and their state, and nothing else.
  • The forge's holder sets a commit's statuses, keeps the delivery's view as one comment on the pull request, and appends to the commit's note under refs/notes/mesh-plan.
  • The build seat builds and checks, asked by the controller as before.

A delivery

Its id is <owner>/<repository>@<twelve characters of its commit>. It holds:

  • the pull request (number, base, head branch, description), or none for a commit that reached the trunk without one;
  • its delivery plan: build plan, deploy plan and verdict, as the controller's planner computed them for its diffset (what ADR 0238 called the "change plan", under the glossary's name);
  • its state, its transitions (the last hundred, each with when, the event, from, to and why), and its machine steps while delivering;
  • once merged, the commit it landed on the trunk as, and the walk that delivers it.

The state table

One table, compiled into mesh-delivery, read by its code, its test, its table verb, the controller's self-check and healer H2. Each state has a bound: how long it may be held before stalled lists it. Each state also says what H2 may do after the bound, which is only ever a transition the table already 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
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 —
published merged on the trunk its modules follow, its walk opened and asking nothing; it waits for its turn or its word 30 minutes superseded when a newer delivery took over its walk; go when its walk started
held it waits for a person; read again each tick, so it ends by itself when it moves nothing or a later merge covers it (ADR 0270) 1 day nothing: it is the operator's
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 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 opened for it within ten minutes is held too, saying so: nothing it moves follows that branch, or the merge was not heard. Nothing waits silently.

What needs no person ends by itself (ADR 0270):

  • a merge that moves nothing (its plan builds nothing, or only adds a module the controller builds and sends nowhere) is delivered as soon as it is merged, whatever its check said;
  • a merge a later delivered merge contains is covered: every module it moves was sent to every machine running it by the walk of a later merge into the same trunk, delivered on its own passing check, and the forge says that later merge commit contains it (gitea_contains, asked once per pair and kept). Merge order is only the first filter, and a forge that cannot answer means not yet covered. mesh/delivery says covered: a later merge that contains it was delivered as a success. A module that runs on one machine only gets no "rest" step and is never covered;
  • the covered row is tried before go, from held and from ready past the ten minutes.

History is retired, not held (ADR 0250). A delivery made from the forge's word at its merge, heard fifteen minutes or more after that merge, with no walk of it open, was replayed from the bus's history: it reached the machines before this owner was there. It goes to retired at adoption, before any check, hold or walk, and its pull request is not told. A held delivery that fits the same rule is retired by a person's retire-history, never released. Nothing of a published delivery is registered before its walk starts, because a send carries every registered build that waits on its machine (ADR 0236 §4a), and a build registered before its turn would be carried by somebody else's send.

The machine steps. While a delivery is delivering, each machine its walk reaches has a row with the module and the build: sent (the first machine's send, or the rest's), judging (the gate's healthy readings so far), passed, failed, rolled-back. They are read from the walk's own record in the controller's plan-moved event, never inferred from time.

A delivery group

  • Membership: the pull request's head branch name, across the mesh's repositories, among open pull requests. Two or more make a group. A group that has started delivering takes no new member.
  • Order: after: <repository> lines in a member's description, and the controller's delivery-order over the graph (ADR 0239 decision 4). The plan shows the order and why each pair is ordered: declared, built by, version skew, engine before controller, by name.
  • Precedence (ADR 0249): when rules order one pair both ways, the higher one decides. Declared comes 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.
  • 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 heads that merged and its own walk is still open (ADR 0270).
  • A failed member: the members after it are stopped, naming it. The members before it stay delivered. Its own builds were put back at its gate.

A group's state is derived from its members and its composed check, and is shown, never stored apart from them.

What every transition does

In this order, each by its owner:

  1. kept: mesh-delivery puts the delivery in its state (deliveries, one key per delivery; groups, one key per group). Nothing is said before it is kept. What it owes outside is kept with it and retried, later each time, from ten seconds doubling to an hour. The forge's answer that what it is for does not exist ends it at once, and sixty failed tries end it too, each said among the owner's refusals (ADR 0250);
  2. said: the event mesh-delivery.transition (and mesh-delivery.group when a group's derived state changes), with the delivery's id, from, to, event, why and plan summary, and no secret or address;
  3. noted: mesh-delivery asks the forge's holder (gitea_note_append) to append a line to the commit's note: the head while the delivery is off the trunk, the commit it landed as once it is on it, and at its end a line of what was executed there. The forge's holder writes it in its own repository as the forge's own account, and a line already there is not appended again;
  4. reflected (not for history, whose pull request the forge may no longer hold): the delivery's view, one comment on the pull request with the state, the plan, the machine steps and the group, kept current (gitea_delivery_view); the status mesh/delivery on the head, and mesh/delivery-group on every member's head (gitea_commit_status). Every status links to the pull request, mesh/merge-gate among them.

The verbs

mesh-delivery's seat (served by its holder; the first five read):

Verb Answers or does
deliveries every delivery not final, and the final ones of the last day, one line each; filtered by state, repository or group
show one delivery or group whole: plan, transitions, machine steps, order, the walk
groups every group with its members in order and its derived state
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
recheck a rejected or ready delivery back to proposed, with why
release a held delivery to delivering, with why: a person's word
stop any delivery not final to stopped, with why; its walk is ended through the controller
close H2's only verb: the transition the table names for a stalled delivery, refused otherwise
retire-history held history to retired, with why: one by id, refused when the rule does not take it, or every held one, answering how many and naming those it left; dry changes nothing

The controller's verbs for it (on the mesh-controller seat): delivery-plan, delivery-order, delivery-check (a group's heads composed, or one head checked again), deliver, delivery-stop, delivery-walks. A person has plans go <plan> --why, which does what deliver does under their name and is recorded as a hand act. The controller says every walk it keeps as plan-moved, from a verb's command too.

The forge's holder's tools for it: gitea_note_append, gitea_delivery_view, gitea_commit_status. It also announces pull.closed, and a merge's head and the statuses the forge holds on it.

The store

Key-value state on the bus, declared by the module (ADR 0201): deliveries and groups. One writer, the seat's holder, whose code changes state from a single goroutine. A final delivery is kept for thirty days and then removed. Its note on the commit keeps its record after that. The bus's own snapshot (ADR 0235) backs it up.

The bootstrap

  • A walk that moves the controller, the node-engine, the tool runner, the bus or mesh-delivery is the controller's own, started by the merge and witnessed on the machine. mesh-delivery records it.
  • Any other walk waits for deliver only while the seat has a holder on record. With none on record, the controller starts it as it always did.
  • A waiting walk is said by the controller whatever mesh-delivery says of itself: S16 raises plan.<walk>.waiting after 30 minutes, urgent after 4 hours, naming plans go <walk> --why as the way on. A holder that is down is also D3's holder-silent; one that is up and never says go is said by S16 alone.

The switch

  1. The controller's change (the seat, its verbs, plan-moved, the wait for a holder's word, plans go) is merged and rolls out as the core does. With no holder on record it behaves exactly as before.
  2. The catalogue's change (mesh-delivery, the forge holder's notes and view) is merged. mesh-delivery is built and published.
  3. A person assigns mesh-delivery to the control node. The seat now has a holder on record. Walks that start from then on wait for its word. Walks already open finish on their own and are adopted as deliveries in delivering.
  4. To step back, unassign it. Waiting walks are then started by the controller at its next pass.

Phases

Phase Delivers Done when
A — the owner mesh-delivery with its table, state, verbs, events and adoption; the controller's seat, verbs, plan-moved and the wait; the forge holder's view, notes and statuses; the group's order and composed check the tests of ADR 0239's How it is checked pass; a merge on the live mesh with mesh-delivery held is delivered by it and shown by deliveries
B — the conditions S16, the controller's own plan.<walk>.waiting; probe D14 reads stalled and raises delivery.<id>.stalled; H2 calling close — built 2026-10-07, on a branch a delivery stalled on purpose is raised and closed by H2 through close; a walk never let go is raised by S16
C — the walk itself the per-tier walk moved into mesh-delivery behind single-send verbs, the controller's planner kept only for the built-in path decided by its own record once Phase A has delivered for a while

What is not decided here

  • A web view of deliveries beyond the pull request's comment.
  • Whether mesh/delivery-group is required on the trunks. That is the operator's setting, through the forge module's protection tool.
  • Moving the per-tier walk out of the controller (Phase C).