Merge pull request 'Issue 362 resolved: ADR 0276 gains the own-path batch rule and a progressive insight, to-be 45 gains S18 and S19' (#277) from issues/362-resolved into main

This commit was merged in pull request #277.
This commit is contained in:
2026-10-10 12:43:19 +00:00
4 changed files with 39 additions and 2 deletions
@@ -164,6 +164,18 @@ either, because **delivery group** already names deliveries that share a head br
repository exist and that none names its merge, or that the controller holds none) and listed by
`stalled` at once, so probe D14 raises it for the operator.
> **Decided during the build, 2026-10-10** (on the operator's delegation). Decision 2 batches every merge of the
> window together, and decision 4 starts a walk on the controller's own path without mesh-delivery's word. A
> batch holding both a merge on that path and a catalogue merge would therefore start the catalogue's deliveries
> without their word: their turn in a delivery group, their holds, and the order of decision 5 would be skipped.
> So **a merge on the controller's own path never shares a batch with a merge that waits for the delivery's
> word.** Such a merge goes into a batch of its own, with its own window; the open catalogue batch closes and is
> cut by the normal rules, and queues behind the own-path walk like any other. Catalogue merges heard during the
> own-path batch's window join the next catalogue batch. An own-path walk being cut folds no catalogue walk that
> waits for its word: that walk's merges are batched again behind it, and the walk names that batch as the one
> that took it over, so no catalogue delivery ever skips its turn. Checked by the controller's test
> `TestAMergeOnTheControllersPathNeverSharesABatch`.
## Consequences
- **A merge waits up to 90 seconds before it is planned**, and up to 10 minutes in a busy period. A walk
@@ -181,6 +193,11 @@ either, because **delivery group** already names deliveries that share a head br
restart-safe; the walk's record names several repositories and commits instead of one, and every reader of
it (`plans`, S3, S16, `plan-moved`, mesh-delivery) changes with it. The store gains the batch and the
merges a walk answers, as a numbered migration and in the consolidated schema.
> **Progressive insight — 2026-10-10.** The controller has no consolidated schema file: a fresh install runs its
> numbered migrations from the first, embedded in the build, so the numbered migration (0089) is the whole of
> the schema change. The bullet above said "as a numbered migration and in the consolidated schema"; that second
> half describes mesh-delivery's kind of store, not the controller's. The decision stands.
- **The replay of issue 362** in the lab raises a mesh, merges two commits of one repository 18 seconds
apart, and passes when one walk delivers both without a person; it fails on the commit before the change.
@@ -4,6 +4,7 @@ status: in-progress
code: [mesh-controller, mesh-host, mesh-tools, mesh-catalog, mesh-sdk, mesh-lab]
updated: 2026-10-10
decisions:
- 02-DECISIONS/0276-merges-are-assembled-in-a-rolling-window-and-each-batch-is-delivered-by-one-walk-with-one-commit-per-repository.md
- 02-DECISIONS/0271-a-send-held-for-the-buss-planned-step-is-told-to-the-operator-at-once-and-a-change-that-needs-it-says-so-before-it-merges.md
- 02-DECISIONS/0265-a-verb-that-reads-is-answered-on-the-serving-controllers-own-connection-and-every-connection-says-what-it-is.md
- 02-DECISIONS/0264-a-message-a-consumer-gives-up-on-is-kept-until-a-person-delivers-it-again-or-drops-it.md
@@ -238,6 +239,8 @@ signal and asserts its condition. `doctor signals` shows, for every row, the age
| S15 | a hand act with a cause already recorded | hand-act log | each act | the second within 14 days; clears when fewer than two remain within 14 days | `healer-wanted` (names the cause, and the healer that was not enough where one answers it) | warning | — |
| S16 | a walk waiting for its delivery's word is let go | mesh-delivery, through `deliver` (ADR 0239) | each merge whose walk waits | 30 min; urgent after 4 h | `waiting` (names the walk and `plans go`) | warning | — |
| S17 | a send held for the bus's planned step is told to a person (ADR 0271) | controller's plan | each send refused because it would replace the bus outside its step | none: the first refusal; cleared once the bus's machine has been sent the build the mesh holds | `bus-step-waiting`, for the operator (names the machines, what waits, the bus build from and to, since when and the `mesh-controller.bus` call); S3 leaves such a walk out | warning | — |
| S18 | a batch of merges is cut into its walk (ADR 0276) | controller's merge window | each batch | a minute past `merge-window-at-most` while no walk is open: the controller failed to cut it | `batch-not-cut` (names the batch and what it holds) | warning | — |
| S19 | a batch waiting behind an open walk is cut when it ends (ADR 0276) | controller's merge window | each batch closed while a walk is open | that walk's bound, a tier's bound for each of its tiers, from when the batch closed | `batch-behind-walk` (names the walk) | warning | — |
The bus advisories (S9) cost one read-only subscription: the server already publishes them. The
controller translates each into a condition naming the thing in the mesh's words, as the refused reply
@@ -130,6 +130,11 @@ controller's `plan-moved` event, never inferred from time.
- **One walk at a time.** Merges that arrive while a walk is open join the next batch. A walk that started
is never superseded. A walk still waiting for its word when the next batch is cut is folded into the new
walk, which answers every merge the folded one answered.
- **The controller's own path.** A merge that moves a module whose walk waits for nobody's word (the controller,
the node-engine, the tool runner, the bus, mesh-delivery) never shares a batch with one that waits for
mesh-delivery's: it has a batch of its own, with its own window, and the catalogue's batch queues behind its
walk like any other. An own-path walk folds no waiting catalogue walk; that walk's merges are batched again
behind it, so no catalogue delivery skips its turn (ADR 0276, decided during the build, 2026-10-10).
- **A late merge.** A merge heard after a later merge of its repository and branch was put in a walk is
answered by that walk: the assembling batch, the open walk, or, when that walk was delivered, it ends
`covered` at once.
@@ -1,8 +1,9 @@
---
status: located
status: resolved
opened: 2026-10-10
located-in: [mesh-catalog modules/mesh-delivery (holder.go deliveryWalking), mesh-controller cmd/mesh-controller (upgrades.go SourceMoved, release_plan.go laterOnTheBranch)]
fixed-by:
fixed-by: mesh-catalog#171, mesh-controller#197
replay: R362
amended-design: 03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md
---
@@ -65,3 +66,14 @@ The operator decided the model that removes this shape, not only its bookkeeping
commit per repository, one walk at a time. The bookkeeping that tied a walk to an ended delivery is repaired as
well, and every wait of this shape has a bound and a condition. It is designed in to-be 47, *The merge window
and the batch*.
## Resolved
2026-10-10. mesh-delivery's side is mesh-catalog#171 (merged): a walk is tied to every live delivery whose
merge it answers, never to one that has ended, and a waiting walk no live delivery holds is listed by `stalled`
at once. The controller's side is mesh-controller#197: the merge window and the batch, one walk per batch with
one commit per repository, the walk naming every merge it answers, and the bounds of decision 9. The replay
R362 is registered in mesh-lab's replays register (mesh-lab#75), proved to fail on the commit before the
mesh-delivery fix and pass on it. The build raised one rule the record had not settled, decided during the
build and written into ADR 0276: a merge on the controller's own path never shares a batch with a catalogue
merge.