Design 51: keep the node-engine's own build readable by away nodes (ADR 0623)
mesh/delivery closed: a newer head of the same pull request
mesh/check pass 01d4f2781ef0 on 6cd965b3cdf6 | unit 39 run, 0 kept, 1 skipped | integration 39 run, 0 kept, 1 skipped | composition passed in 33s on 4…

Under ADR 0618 alone a node away with an old node-engine would be held
from the node-engine's own build in the new form and could never update
itself. ADR 0623 keeps every counted node-engine's form in those builds
and moves them to a node that reads any one of them.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 09:48:56 +01:00
parent 48fa0a5a48
commit 01d4f2781e
@@ -19,6 +19,7 @@ decisions:
- "ADR 0613"
- "ADR 0617"
- "ADR 0618"
- "ADR 0623"
- "ADR 0606"
- "ADR 0607"
- "ADR 0610"
@@ -379,25 +380,30 @@ publish of mesh-sdk or `mesh-contracts` triggers their users (ADR 0614 §6). The
build and adds none (ADR 0613 §1). ADR 0614 bounds nothing here; a bound, such as a settle before building a
fingerprint whose inputs still move, is a question for a record, put to the operator, and is not designed here.
**The node-engine's own build keeps the old reference form** until every present node-engine states the capability
to read the new one (ADR 0618 §2): the builder writes a new reference form, in the node-engine's done key as in every
other build's, only once every node-engine on a node present states it, so no build, the node-engine's own included,
needs a form no running node-engine reads (ADR 0603 §7, §9). Each build names with it the reader capabilities its
forms need, and the assigner holds a node's want while that node's engine does not state one (ADR 0618 §1), so a node
that was away is held, never handed a form it cannot read. This is a window like the old seat name's. The builder
reads each node's stated capabilities through the node-engine seat's verb `manifest-reads` (ADR 0618 §3) at its start,
and wakes on the seat's event `mesh.seat.node-engine.event.manifest-reads-changed`, said when a node's stated
capabilities change and when the node returns after being away (ADR 0618 §4), never on a watch of the node-engine's
have state (ADR 0596) and never on a timer. The builder declares `seat:node-engine.manifest-reads` in its `invokes`:
that is the grant the grants part composes, and with it the grants part grants the builder the subscription to the
event's subject. A node-engine that does not yet serve `manifest-reads` counts as stating nothing: the window stays
open and names the node. Only a present node-engine that has not updated holds this window; a node away is held by the
assigner instead and is not listed as holding it. Its tool `builder_old_form` lists whether the window is open and the
present nodes whose node-engine does not yet state the capability, and drops a retired node from it by hand, recorded
as a hand act; a present node holding it open for seven days is the builder's finding naming the node, cleared when
the window closes. Closing it says so in the build log and emits `old-form-closed` (the time, the nodes that held
it last, the nodes dropped by hand) on the builder's own family beside `numbered`; a waiter on a build's end does not
wake on it.
**The node-engine's own build keeps the old reference form** while any node-engine the mesh counts states only it,
away ones included (ADR 0623 §1-2). For the module that holds the seat `node-engine`, the builder writes into each
build key every reference form a counted node-engine states, beside the new form, which it writes there as in every
other build only once every present node-engine states it (ADR 0618 §2); a node leaves the count only when it is
retired, never because it is away (ADR 0623 §1). The assigner moves the node-engine's own build to a node once that
node's engine states any one form the build carries (ADR 0623 §2), so a node back from being away moves to the new
node-engine through the old form, states the new capabilities from then on, and can always update itself (ADR 0603
§7, §9). Every other module's builds keep ADR 0618 §1-2: they carry the new form once every present node-engine
states it, each names the reader capabilities its forms need, and the assigner holds a node's want while that node's
engine does not state one, so a node that was away is held from them, never handed a form it cannot read, until its
new node-engine states the form. The old form in the node-engine's own builds is a window like the old seat name's:
it closes when no counted node-engine states the old form alone, and the builder then drops it from those builds. The
builder reads each node's stated capabilities through the node-engine seat's verb `manifest-reads` (ADR 0618 §3) at
its start, and wakes on the seat's event `mesh.seat.node-engine.event.manifest-reads-changed`, said when a node's
stated capabilities change and when the node returns after being away (ADR 0618 §4), never on a watch of the
node-engine's have state (ADR 0596) and never on a timer. The builder declares `seat:node-engine.manifest-reads` in
its `invokes`: that is the grant the grants part composes, and with it the grants part grants the builder the
subscription to the event's subject. A node-engine that does not yet serve `manifest-reads` counts as stating
nothing: the window stays open and names the node. Its tool `builder_old_form` lists whether the window is open and
the counted nodes, present or away, whose node-engine states only the old form, and drops a retired node from the
count by hand, recorded as a hand act; a node holding it open for seven days is the builder's finding naming the node,
cleared when the window closes. Closing it says so in the build log and emits `old-form-closed` (the time, the nodes
that held it last, the nodes dropped by hand) on the builder's own family beside `numbered`; a waiter on a build's end
does not wake on it.
**When the group is pushed.** Only once the release that adds the node-engine's stated capability (design 47) runs on
every node, read from the status view's haves before the push, and once the progressive insights of ADR 0595 and
@@ -487,14 +493,15 @@ test).
source other than the publish target) the floor finding is written and cleared once it answers, and with
`bridge_tags` still silent after the by-digest publish, the build stays unnumbered until the forge bridge's health
clears (no timer runs), and is then numbered and published by version; `builder_floor_again` asks the three
sources at once and records the hand act; the node-engine's done key stays in the old form while one present node's
node-engine lacks the capability, or does not serve `manifest-reads`, and is written in the new form once every
present node states it, `builder_old_form` naming that node meanwhile and dropping it by hand with a hand act; with
one node away whose node-engine lacks the capability, the new form is written, the assigner holds that node's want,
and `builder_old_form` does not list it (ADR 0618 §1, §2); a present node gaining the capability closes
that window on its `manifest-reads-changed` event with no `delivered` and no timer (ADR 0618 §2, §4), while a node
away is held by the assigner from builds in the new form (ADR 0618 §1), with `old-form-closed` emitted
and its build-log line written, and a waiter on a build's end does not wake on it; with the image's own seat silent
sources at once and records the hand act; a build key carries only the old form while one present node's
node-engine lacks the capability, or does not serve `manifest-reads`, and carries the new form once every present
node states it (ADR 0618 §2); with one node away whose node-engine lacks the capability, the node-engine's own build
still carries the old form beside the new and is moved to that node, while another module's build in the new form
is held by the assigner for it (ADR 0623 §1-2, ADR 0618 §1), `builder_old_form` naming that node meanwhile and
dropping a retired one from the count by hand with a hand act; that node, back with the new node-engine, says
`manifest-reads-changed` and the window closes with no `delivered` and no timer (ADR 0618 §4), the old form dropped
from the node-engine's own builds, with `old-form-closed` emitted and its build-log line written, and a waiter on a
build's end does not wake on it; with the image's own seat silent
at the claim of `distribution`'s own image, the image is still built, published by its digest, and numbered once
its new build answers (ADR 0617 *How it is checked*).
- **Builder, added for the milestone, unit** (cases of the builder's numbering): a second trunk build of a package's