Design 47 takes in round 1 of the review by architectural domain
The reviewers found the amendment left the stores to grow without a bound, the waits without an owner's tools or events, a rollback that would send nodes back to old builds, a newer indexer that could never be wanted, events any account could forge, and the node-engine reading every node's placements. The design now chooses, each with its reason: a default record retention and caps with fill conditions, a revision removed when no record pins it and it is not current, waits held and released by each step's own part with their events, the build module's wait ending on the agreed toolchain, the old keys kept written until a named milestone H for a rollback, the running indexer making the newer indexer's entry, rule changes named by the running checker from outside the sandbox, and subjects and grants that let each part say only its own. The review verb leaves milestone G for issue 1782, and the watcher's definition goes back to main, since it contradicted an approved instruction. Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
@@ -23,13 +23,8 @@ without that read on each machine the module is wanted on.
|
||||
Loop: wait with `mesh_wait` on the event family (its answer only wakes you), then read the state from the verb
|
||||
the handover names; never report a state you did not read in that round. Report and end at the first of: the
|
||||
thing reached its end (passed, merged, delivered, accepted, chosen, declined), it failed (quote every failure
|
||||
line word for word), the bound passed (say what you last read, when, and since when nothing moved), or a call failed
|
||||
twice (quote it).
|
||||
|
||||
**Never end on a quiet five minutes.** Your final report is your only channel to the lead: once you end, nothing
|
||||
watches the thing. Five minutes with no change while something should be moving is no end: note it, keep waiting,
|
||||
and put it in your final report (what stood still, from when to when, what you last read). A lead that wants to hear
|
||||
of stillness sooner gives a shorter bound.
|
||||
line word for word), five minutes passed with no change while something should be moving (say what you last
|
||||
read and when), the bound passed, or a call failed twice (quote it).
|
||||
|
||||
You only read: no verb that writes, never ssh, never a shell helper. Report in a few lines, with times in UTC as
|
||||
the tools give them; the lead says them to the operator in local time.
|
||||
|
||||
+1
-1
@@ -552,7 +552,7 @@ controller (the planner, the rollout) until release 6 of ADR 0429; from each rel
|
||||
fingerprints, served by the seat `mesh-catalog`'s verb `revision`, and the assignment graph computed from it,
|
||||
served by the seat `mesh-wants`'s verb `revision`, for a trunk revision or a candidate's heads; a pair, each half
|
||||
served by its one owner (ADR 0656; the verbs' names, design 47). A part with none for the current revision waits
|
||||
and says so (ADR 0656).
|
||||
and says so (ADR 0656). The node-engine reads only the catalog half, beside its want (design 47).
|
||||
- **delivery record** — the gate's record of one milestone's delivery, a ledger instance it alone writes: the group's
|
||||
state (heads, verdicts, checks, asks), the trace (milestone, issues, pull requests, commits, the assignment graph
|
||||
revisions it moved between) and what happened to each entry on each node (ADR 0656). It holds no tiers and nothing
|
||||
|
||||
@@ -227,7 +227,7 @@ source revision is derived from the keys: every **want** equals its module's **f
|
||||
changed by a proposal (ADR 0567; ADR 0446 §3 read as written). Its own composition stands in for every sealed value, so only a node's answer to a proposal can say that
|
||||
what the node would run is the same. From research 085's milestone it computes the assignment graph from the
|
||||
catalog graph, the placements and the nodes' capabilities, keeps each revision (ADR 0656) as objects
|
||||
in its manifest's existing `objects` section (ADR 0619 §2), serves it and a change's graph difference by verbs of
|
||||
in an `objects` section in the old form (ADR 0619 §2), serves it and a change's graph difference by verbs of
|
||||
its seat `mesh-wants`, and writes the wants from a trunk revision's assignment graph alone (ADR 0656).
|
||||
- **The node agent**, the node-engine's own process, follows its node's wants, **composes each wanted module for
|
||||
its own node** with the composition of `mesh-delivery-sdk` from the manifest by digest, the module's resolved values from
|
||||
@@ -407,7 +407,8 @@ watches that key and stops only when the head in it moves; a trunk move never en
|
||||
|
||||
### The delivery record
|
||||
|
||||
*ADR 0656; ADR 0595, ADR 0596, ADR 0597, ADR 0603 §7, ADR 0493 §3, §11, ADR 0633 §4, §5, ADR 0441 §1, ADR 0548 §8.*
|
||||
*ADR 0656; ADR 0595, ADR 0596, ADR 0597, ADR 0603 §7, ADR 0493 §3, §11, ADR 0633 §4, §5, ADR 0441 §1, ADR 0548 §8,
|
||||
ADR 0564 §2, ADR 0363 §2.*
|
||||
|
||||
From research 085's milestone the gate, holder of the seat `mesh-delivery`, keeps one **delivery record** per
|
||||
milestone's delivery, a ledger instance (ADR 0595's template `ledger`, ADR 0597) it alone writes (ADR 0656). It
|
||||
@@ -417,18 +418,25 @@ holds:
|
||||
- **the trace**: the milestone, its issues, its pull requests, their commits, and the graph revisions the delivery
|
||||
moved between;
|
||||
- **what happened to each entry on each node**: for every entry of the graph difference, taken in, built, checked,
|
||||
composed, wanted, running healthy, or away (ADR 0656).
|
||||
composed, wanted, running healthy, held (with the hold's reason, so a reader of the record sees why an entry stands
|
||||
still without asking its holder), failed (with what failed), or away (ADR 0656).
|
||||
|
||||
It holds no tiers, and only the gate orders work by it, so it is no second copy of the keys, the objection research
|
||||
063 had to a stored plan (research 085, Findings 10). Its fields, retention and tools are this design's choices under
|
||||
ADR 0656.
|
||||
|
||||
- **The outcomes arrive as events, through a durable consumer of the gate's own.** The gate's manifest `consumes`
|
||||
each step event of *What each step says* (below). The consumer resumes from the last event applied; an event
|
||||
applied twice changes nothing; an event is applied only when it comes from its owner's account; and running
|
||||
healthy is taken from the node-engine seat's `running` event, never from a have read across the seam (ADR 0596).
|
||||
- **It ends when every present node runs its entries.** It names the nodes away, each with since when, and ends
|
||||
without waiting for them, as a node away holds nothing (ADR 0603 §7).
|
||||
each step event of *What each step says* (below), and `wait-held` and `wait-ended` of each holder. The consumer
|
||||
resumes from the last event applied; an event applied twice changes nothing; an event is applied only when it comes
|
||||
from its owner's account; and running healthy is taken from the node-engine seat's `running` event, never from a
|
||||
have read across the seam (ADR 0596).
|
||||
- **It ends when every present node runs its entries**, and the gate says `record-ended` on the seat `mesh-delivery`
|
||||
with the record's milestone and its nodes away. It names the nodes away, each with since when, and ends without
|
||||
waiting for them, as a node away holds nothing (ADR 0603 §7).
|
||||
- **A record open too long is a finding.** The watchman writes the finding `record-open` for a record still open 24
|
||||
hours after its merge (a delivery of the whole mesh takes under an hour, so a day means something stands still) and
|
||||
clears it on `record-ended`; the condition keeper raises it (ADR 0564 §2). The finding names the entries still held
|
||||
or failed, read from the record's own events.
|
||||
- **A node away that wakes adds its outcomes.** When it wakes and catches up by its wants (*A change's graph
|
||||
difference is its delivery*, below), its outcomes reach the record through the same consumer as any other, and the
|
||||
record shows the node no longer away.
|
||||
@@ -440,40 +448,48 @@ ADR 0656.
|
||||
delivery record like any milestone; nothing is merged outside a released milestone (ADR 0493 §11).
|
||||
- **It pins the graph revisions it points at.** The gate says, as the seat `mesh-delivery`'s events `pinned` and
|
||||
`freed`, which catalog and assignment graph revisions a record starts and stops pointing at, and as
|
||||
`heads-replaced` that a candidate's heads were replaced or its pull request closed; the indexer and the assigner keep
|
||||
and drop their revisions and a candidate's graphs only on these events, never by reading the gate's state
|
||||
(ADR 0596; *Two graphs, one source of truth*, below).
|
||||
- **A record is kept for good unless the gate's manifest sets a retention.** When the retention removes a record,
|
||||
the gate says `freed` for each revision it pinned.
|
||||
`heads-replaced` that a candidate's heads were replaced or its pull request closed. Only the gate's account may
|
||||
publish them (ADR 0363 §2). The indexer and the assigner hear them through a durable consumer each, declared in
|
||||
their manifests' `consumes`, which resumes from the last event applied after a restart, so a `freed` said while one
|
||||
of them was down is still applied; neither reads the gate's state (ADR 0596; *Two graphs, one source of truth*,
|
||||
below).
|
||||
- **A record is kept for 90 days by default**, the gate's setting `record-retention`. Ninety days covers every trace
|
||||
the operator has asked of a past delivery so far, which went back weeks, never months; the setting can keep records
|
||||
longer. When the retention removes a record, the gate says `freed` for each revision it pinned.
|
||||
- **Its size, its cap and its growth.** One record of 30 modules on four nodes is about 30 KiB, against the bus's
|
||||
256 KiB value limit (research 085, Findings 8). At an estimated 20 deliveries a day (a guess from the days of
|
||||
research 085, not a measurement) the ledger grows about 0.6 MiB a day, about 54 MiB at the default retention; its
|
||||
cap is 128 MiB.
|
||||
- **The switch carries today's state in, and a rollback reads it back.** At the new gate's start, `merges`, `turns`
|
||||
and every group in flight become records, and the new gate keeps `merges` and `turns` current beside the records
|
||||
until a later change removes them, so a gate rolled back reads current state and no approved group is asked again.
|
||||
and every group in flight become records, and the new gate keeps `merges` and `turns` current beside the records,
|
||||
so a gate rolled back reads current state and no approved group is asked again; milestone H (*Milestones*) stops
|
||||
writing them.
|
||||
- **The forge bridge asks the seat for a group.** It reads a group's members from the seat `mesh-delivery`'s verb
|
||||
`groups`, never the gate's `merges` state, both to set the group on each merged message and to publish a group's
|
||||
end again (ADR 0656, which changes ADR 0633 §4 and §5; ADR 0596).
|
||||
- **Its size.** One record of 30 modules on four nodes is about 30 KiB, against the bus's 256 KiB value limit and a
|
||||
64 MiB bucket (research 085, Findings 8).
|
||||
end again (ADR 0656, which changes ADR 0633 §4 and §5; ADR 0596). Its account holds no grant to read `merges`.
|
||||
- **Its tools**, against the four lines a module's tools answer:
|
||||
|
||||
| Line | The gate |
|
||||
|---|---|
|
||||
| read everything it holds | `gate_record` (one record whole: the group's state, the trace, each entry's outcome per node, the nodes away), `gate_records` (every record with its fill against the value limit), `gate_consumer` (its durable consumer: the last event applied per family, the events waiting, the age of the oldest) |
|
||||
| do by hand what it does itself | `gate_record_repair` (ask each part for its outcome again and apply the answers, completing a record missing one) |
|
||||
| read everything it holds | `gate_record` (one record whole: the group's state, the trace, each entry's outcome per node, the nodes away), `gate_records` (every record with its fill against the value limit, and the ledger's fill against its cap), `gate_consumer` (its durable consumer: the last event applied per family, the events waiting, the age of the oldest) |
|
||||
| do by hand what it does itself | `gate_record_repair` (for one record, asks each owner for the outcome of each entry missing one through that owner's read verb: the indexer's `take-in` read, the builder's build read, the checker seat's check read, the seat `mesh-wants`'s `entry`, and the node-engine seat's have read of that node; applies the answers as the consumer would) |
|
||||
| recover without help | `gate_record_end` (end a record left open, a node gone for good or an entry that never runs, with the reason, recorded in the hand-act log of the seat `mesh-hand-acts`) |
|
||||
| one seat, many tools | the seat `mesh-delivery`'s verbs, with `groups` answering a group's members |
|
||||
|
||||
- **How it is checked.** the gate's whole-module test stops and restarts the gate in the middle of a
|
||||
delivery, and the record is complete with no outcome counted twice; live, one call of `gate_record` traces an
|
||||
issue of the registry milestone to each node's running build . In the gate's whole-module
|
||||
test: the events `pinned`, `freed` and `heads-replaced` are said; a group approved before the
|
||||
switch is not asked again after it, nor after a rollback; a record ends once every present node runs its entries,
|
||||
naming the nodes away; a node away that wakes adds its outcomes and is no longer shown away; a group's heads
|
||||
approved and checked again ask the operator nothing again; a small fix's merge gets a record of its own; a record
|
||||
removed by a set retention frees its revisions; the tools read a record, list the records with their fill, and a
|
||||
repair completes a record missing an outcome. In the forge bridge's whole-module test, a group's members are read
|
||||
from `groups` and its end published again from it. Live: the trace also holds after six later merges; a node away
|
||||
is named with since when and its outcome taken on waking; a record of 30 modules on four nodes stays under
|
||||
256 KiB; a group checked again at old heads after a main move is not asked of the operator again (issue 1972).
|
||||
- **How it is checked.** In the gate's whole-module test: the gate stopped and restarted in the middle of a delivery
|
||||
leaves the record complete with no outcome counted twice; the events `pinned`, `freed`, `heads-replaced` and
|
||||
`record-ended` are said; a `freed` from an account other than the gate's is refused by the bus; a group approved
|
||||
before the switch is not asked again after it, nor after a rollback; a record ends once every present node runs its
|
||||
entries, naming the nodes away; a held and a failed entry are kept with their reason; a record open past 24 hours
|
||||
raises `record-open`, cleared by `record-ended`; a node away that wakes adds its outcomes and is no longer shown
|
||||
away; a group's heads approved and checked again ask the operator nothing again; a small fix's merge gets a record
|
||||
of its own; a record past its retention is removed and frees its revisions; the tools read a record, list the
|
||||
records with their fill, and a repair completes a record missing an outcome through the owners' read verbs. In the
|
||||
forge bridge's whole-module test, a group's members are read from `groups` and its end published again from it, and
|
||||
a read of `merges` by its account is refused. Live: one call of `gate_record` traces an issue of the registry
|
||||
milestone to each node's running build, also after six later merges; a node away is named with since when and its
|
||||
outcome taken on waking; a record of 30 modules on four nodes stays under 256 KiB; a group checked again at old
|
||||
heads after a main move is not asked of the operator again (issue 1972).
|
||||
|
||||
## The state table
|
||||
|
||||
@@ -512,7 +528,7 @@ module's progress on each node is its want against its have, shown by the view (
|
||||
|
||||
*ADR 0656, which supersedes ADR 0645 to ADR 0648; ADR 0595,
|
||||
ADR 0596, ADR 0603 §2, §6, §7, ADR 0567 §5, ADR 0571 §8, ADR 0614 §4, ADR 0618 §2, ADR 0619 §1 to §3, ADR 0636 §1,
|
||||
§4, §7, ADR 0639 §7, §8.*
|
||||
§3, §4, §7, ADR 0639 §7, §8, ADR 0564 §2, ADR 0363 §2.*
|
||||
|
||||
From research 085's milestone. One graph answered two questions, which modules exist and which version runs where,
|
||||
and one module running as several placed versions would have given one entry two shapes and one key two writers; two
|
||||
@@ -523,7 +539,7 @@ Findings 11). How each is kept, read and retained is this design's choice under
|
||||
manifests ──► indexer (mesh-catalog) ──► catalog graph revision ──┐
|
||||
├──► assigner (mesh-wants) ──► assignment graph revision
|
||||
placements (mesh-module-assigner) ───────────────────────────────┤ │ │
|
||||
node capabilities (node records) ────────────────────────────────┘ │ └─► wants, from a trunk revision only
|
||||
node capabilities (node-engine seat) ────────────────────────────┘ │ └─► wants, from a trunk revision only
|
||||
▼
|
||||
a change's assignment graph − the current one = its graph difference = its delivery
|
||||
```
|
||||
@@ -535,35 +551,60 @@ Findings 11). How each is kept, read and retained is this design's choice under
|
||||
fingerprint, with the rules the seats declare (*An acting part's new version acts first*, below).
|
||||
- **The assignment graph is the assigner's, computed and never written by hand.** The assigner, holder of the seats
|
||||
`mesh-module-assigner` and `mesh-wants`, computes the module versions placed on nodes, with the edges between
|
||||
versions, from the catalog graph, the placements and the nodes' capabilities, and nothing else writes it (ADR 0656
|
||||
§1). Each entry is one module version on a node; its edges are provisioning, contribution, and the acting parts'
|
||||
versions that are to act on it (ADR 0656), whose rules and versions come in with the catalog graph. It is kept, but
|
||||
it is no stored plan: it has one writer, no part orders work by a stored plan, and any revision is computed again
|
||||
from the inputs it names and compared with the one kept, by a tool (below), so a kept revision is a checked
|
||||
versions, from the catalog graph, the placements and the nodes' capabilities, and nothing else writes it
|
||||
(ADR 0656). Each entry is one module version on a node; its edges are provisioning, contribution, and the acting
|
||||
parts' versions that are to act on it (ADR 0656), whose rules and versions come in with the catalog graph. It is
|
||||
kept, but it is no stored plan: it has one writer, no part orders work by a stored plan, and any revision is computed
|
||||
again from the inputs it names and compared with the one kept, by a tool (below), so a kept revision is a checked
|
||||
derivation, never a second source of the kind research 063 removed (research 085, Findings 5).
|
||||
- **Each graph is kept per revision, and each revision names its inputs** (ADR 0656). The indexer keeps a catalog
|
||||
graph revision for each source revision it takes in; the assigner keeps an assignment graph revision for each change
|
||||
of its inputs, naming the catalog graph revision, the placements and the capability readings it was computed from.
|
||||
Both parts are the foundation (ADR 0619 §1), so both keep their revisions as objects declared in their manifests'
|
||||
existing `objects` sections, each with a cap it declares there, never in the new form (ADR 0619 §2), and neither
|
||||
waits on the bus module to start; the manifest validator refuses either manifest that declares them in the new form
|
||||
Both parts are the foundation (ADR 0619 §1), so both keep their revisions as objects declared in an `objects`
|
||||
section in the old form, each with a cap it declares there, never in the new form (ADR 0619 §2), and neither waits
|
||||
on the bus module to start; the manifest validator refuses either manifest that declares them in the new form
|
||||
(ADR 0619 §3). An assignment graph revision is announced by an event of the seat `mesh-wants` and served by its
|
||||
verbs. This replaces ADR 0603 §2's one key per module with five past values (ADR 0656, which changes ADR 0603 §2);
|
||||
until research 085's milestone is delivered, those keys and their five values stay as they are.
|
||||
verbs. This replaces ADR 0603 §2's one key per module with five past values as the graph's form (ADR 0656, which
|
||||
changes ADR 0603 §2); the keys themselves stay written beside the revisions until milestone H, so that a rolled-back
|
||||
indexer and assigner read current state (*Rolled back*, below).
|
||||
- **A revision is made by a merge, and also with no merge.** The indexer makes a catalog graph revision when it
|
||||
takes a source revision in. The assigner makes an assignment graph revision on each new catalog graph revision, on
|
||||
the seat `mesh-module-assigner`'s event `placement-changed` (ADR 0567 §5), and on a change of the capabilities a
|
||||
node-engine states in its node record (ADR 0614 §4). A placement change is traced like a merge.
|
||||
- **A revision is kept while a delivery record pins it.** A revision of either graph, and the input revisions it
|
||||
names, is kept as long as a delivery record points at it: the indexer and the assigner remove one only on the gate's
|
||||
event `freed`, never on a timer and never by reading the gate's state (ADR 0596; *The delivery record*, above).
|
||||
While records are kept for good, the revisions they pin are kept with them. This is the graphs' retention in place
|
||||
of ADR 0603 §2's five past values, which ADR 0656 leaves here (its Consequences).
|
||||
the seat `mesh-module-assigner`'s event `placement-changed` (ADR 0567 §5), and on the node-engine seat's event
|
||||
`capabilities-changed`, which a node-engine says when the capabilities it states in its node record change
|
||||
(ADR 0614 §4), so the assigner follows an event and never reads a node record across the seam (ADR 0596). A
|
||||
placement change is traced like a merge.
|
||||
- **A revision is kept while a record pins it or it is current.** A revision of either graph, and the input revisions
|
||||
it names, is removed when no delivery record pins it and it is not current: neither trunk's newest revision nor the
|
||||
newest of an open candidate. Pins are counted per revision, so a revision two records point at stays until both
|
||||
have said `freed`. The indexer and the assigner remove one only on applying `freed` or on a revision ceasing to be
|
||||
current, never on a timer and never by reading the gate's state (ADR 0596; *The delivery record*, above). A trace
|
||||
must read every revision it moved between, and a revision neither pinned nor current is read by nobody.
|
||||
- **The caps and the growth** (estimates, to be read from the fill tools once the milestone runs). An assignment graph
|
||||
revision of about 120 modules on four nodes is under the bus's 256 KiB value limit (its unit test), and a catalog
|
||||
graph revision of about 120 entries about 120 KiB. A record pins the revisions before and after its delivery, and
|
||||
consecutive records share one, so at an estimated 20 deliveries a day about 20 revisions of each graph a day stay
|
||||
pinned: about 4 MiB a day of assignment graph and 2.4 MiB of catalog graph, about 360 MiB and 216 MiB at the
|
||||
records' default retention of 90 days. The caps are 512 MiB for each. Placement-only and capability-only revisions
|
||||
are pinned by no record and go when they stop being current.
|
||||
- **A store filling is said before it is full.** The indexer, the assigner and the gate each say their fill against
|
||||
its cap in their read tools, and the event `filling` of their seat when a store passes 80 % of its cap; the watchman
|
||||
writes the finding `store-filling` naming the part and the store, the condition keeper raises it (ADR 0564 §2), and
|
||||
it clears when the store falls below 70 %. A full cap refuses loudly, naming the part and the store: the indexer
|
||||
keeps no new revision and says the merge pending with the reason `objects full`, the assigner keeps its last
|
||||
revision and writes no new want, and the gate opens no new record and holds the merge; each says it as the event
|
||||
`full` of its seat, which the condition keeper raises as urgent. Nothing is dropped to make room: a removal is only
|
||||
the rule above, and the setting `record-retention` or a larger cap is the operator's.
|
||||
- **What happened is not in the graph.** An entry says what is to run and what it waits on; whether it was built,
|
||||
wanted or runs healthy is said by the parts as their events and kept in the delivery record (ADR 0656).
|
||||
- **The want stays the one record a node reads.** The assigner writes `want.<node>.<module>` from a trunk
|
||||
revision's assignment graph only; a node-engine reads its want, never the graph, and the have stays what it runs
|
||||
(ADR 0656, which changes ADR 0571 §8).
|
||||
revision's assignment graph only; a node-engine reads its want, never the assignment graph, and the have stays what
|
||||
it runs (ADR 0656, which changes ADR 0571 §8).
|
||||
- **Rolled back.** A milestone that has to be reverted brings back the indexer and the assigner of before it. They
|
||||
read ADR 0603 §2's per-module keys and write the wants, both of which the new indexer and assigner keep writing,
|
||||
current, beside the revisions; the want's form is unchanged. So a reverted indexer and assigner start from current
|
||||
state, and no want goes back to a fingerprint older than the one each node runs. Writing the old keys is chosen over
|
||||
converting the revisions back at a rollback because a rollback is the moment nothing new should have to run. The
|
||||
later change that removes them is milestone H, once milestone G has run for one record retention with no rollback.
|
||||
|
||||
### A change's graph difference is its delivery
|
||||
|
||||
@@ -576,8 +617,8 @@ Findings 11). How each is kept, read and retained is this design's choice under
|
||||
`difference`, with the waits and holds read through their owners' tools and the pending revisions through
|
||||
`indexer_pending`.
|
||||
- **The preview is a candidate's difference.** Issue 1874's plan preview of a group before its merge is its
|
||||
candidate's difference, read by one call of `difference`, and needs no code of its own: a candidate's graphs are computed for its check
|
||||
anyway, so the preview costs nothing more.
|
||||
candidate's difference, read by one call of `difference`, and needs no code of its own: a candidate's graphs are
|
||||
computed for its check anyway, so the preview costs nothing more.
|
||||
- **A changed fingerprint with no difference is refused by name.** When a module's fingerprint in the change
|
||||
differs from the running one while the difference is empty, the assigner refuses it, naming the module, and the
|
||||
check fails naming it.
|
||||
@@ -586,9 +627,11 @@ Findings 11). How each is kept, read and retained is this design's choice under
|
||||
were replaced or its pull request closed. A candidate costs a computed graph per check.
|
||||
- **Only a trunk revision writes wants**, whether a merge taken in or a placement or capability change made it; a
|
||||
candidate's graph writes none (ADR 0656).
|
||||
- **Each part acts on its own entries.** The builder, the build modules, the grants part and the node-engine each act
|
||||
when their own entries in the new revision differ from what they run (ADR 0656), reading them through the seat
|
||||
`mesh-wants`'s verbs and events, never its bus state (ADR 0596, ADR 0656), and naming no other module (ADR 0656).
|
||||
- **Each part acts on its own entries.** The builder, the build modules and the grants part each act when their own
|
||||
entries in the new revision differ from what they run (ADR 0656), reading them through the seat `mesh-wants`'s verbs
|
||||
and events, never its bus state (ADR 0596), and naming no other module (ADR 0656). The node-engine acts on its want
|
||||
alone, as it does today: the want is the one record a node reads, and handing every node the assignment half would
|
||||
have each node read every other node's placements.
|
||||
- **A node asleep catches up when it wakes.** A node away holds nothing and catches up by its wants (ADR 0603 §7);
|
||||
a want's new form reaches only a node-engine that says it reads it (ADR 0614 §4, ADR 0618 §2).
|
||||
- **No delivery goes ahead of a change.** A change is delivered as its own difference, its acting parts' new versions
|
||||
@@ -604,17 +647,24 @@ Findings 11). How each is kept, read and retained is this design's choice under
|
||||
inputs, the catalog graph revision, the placements and the capability readings. A part's view for the current
|
||||
revision is the newest assignment half and the catalog half it names. `seat-definitions` stays the seat list's verb
|
||||
(ADR 0636 §4), and the catalog half carries the same definitions at its revision.
|
||||
- **Every part takes a first view, then follows the events.** The checker, the builder, the grants part, the
|
||||
node-engine and the indexer's own later passes take a first view from the two verbs and then follow the two seats'
|
||||
events, never a list compiled into their build nor another module's bus state (ADR 0656, ADR 0596). Of the view the
|
||||
assigner reads only the catalog half, never its own output back; its other inputs stay the placements and the
|
||||
capabilities (ADR 0656). A running part acts only on a trunk revision's view; a candidate's view is read only by
|
||||
the parts that judge a candidate, inside the check its manifest validator and composer, and the indexer's candidate
|
||||
pass (ADR 0656, which changes ADR 0636 §4 in that the candidate pass joins them).
|
||||
- **Every part takes a first view, then follows the events.** The checker, the builder, the grants part and the
|
||||
indexer's own later passes take a first view from the two verbs and then follow the two seats' events, never a list
|
||||
compiled into their build nor another module's bus state (ADR 0656, ADR 0596). The node-engine reads only the catalog
|
||||
half, for the seat definitions it composes with, and its want; it never reads the assignment half (*Each part acts on
|
||||
its own entries*, above). Of the view the assigner reads only the catalog half, never its own output back; its other
|
||||
inputs stay the placements and the capabilities (ADR 0656). A running part acts only on a trunk revision's view; a
|
||||
candidate's view is read only by the parts that judge a candidate, inside the check its manifest validator and
|
||||
composer, and the indexer's candidate pass (ADR 0656, which changes ADR 0636 §4 in that the candidate pass joins
|
||||
them).
|
||||
- **A part with no view says it waits.** It names the revision it has no view for, acts on nothing new, and keeps
|
||||
running what it runs, as ADR 0636 §1 has a reader of the seat list do; the checker, the builder and the grants part
|
||||
wait too, and wait for the view, not only the seat list (ADR 0656, which changes ADR 0636 §1). A part restarted
|
||||
while the indexer is down waits and says so.
|
||||
wait too, and wait for the view, not only the seat list (ADR 0656, which changes ADR 0636 §1); the node-engine waits
|
||||
for the catalog half as ADR 0636 §1 already has it wait for the seat list. Each answers `waits` in its runtime tool
|
||||
(below) with the revision it waits for and since when, and after five minutes without a view writes the finding
|
||||
`view-waits` naming itself and the revision, as a reader of the seat list does, which the condition keeper raises
|
||||
(ADR 0564 §2); it clears when the view arrives. Five minutes is the bound the seat list's readers already keep, so an
|
||||
indexer or assigner down for a restart raises nothing. A part restarted while the indexer or the assigner is down
|
||||
waits and says so.
|
||||
- **Each process knows its own build from its start.** The node-engine hands every process it starts the
|
||||
fingerprint of the build it starts it with, and the process takes its own build from that, never learning it later
|
||||
(ADR 0656, which changes ADR 0639 §7 from the indexer to every process). *The fingerprint handover*, below, says its
|
||||
@@ -624,17 +674,21 @@ Findings 11). How each is kept, read and retained is this design's choice under
|
||||
|
||||
ADR 0656 leaves how each part is built to this design, under issue 1921; these four needed a shape of their own.
|
||||
|
||||
- **An acting rule's fields.** The seat's definition is where ADR 0656 has an acting part declare what it acts on. A seat's definition gains one optional field `acts`, with
|
||||
two fields of its own: `step`, one of `take-in`, `validate`, `check`, `build`, `compose`, `grant` and `place`; and
|
||||
`on`, either `every` (every module) or a `language` naming the language of the modules it acts on, matched against
|
||||
what the manifest says its language is, as the indexer's language map matches today. The definition format's own
|
||||
schema (design 26) gains the field; the indexer reads it into the catalog graph, the assigner into edges, and the
|
||||
checking program from the revision view. **Its cost in mesh-sdk:** the runtime in every module reads a definition
|
||||
only at the seat list's grain (name, scope, verbs, provision) and reads no `acts`; if the runtime's decoder refuses
|
||||
a field it does not read, it gains a pass-over of unread fields, which is a change of mesh-sdk's runtime and
|
||||
rebuilds every module once. That rebuild is the same one the fingerprint handover makes (ADR 0656, Consequences), so
|
||||
the milestone rebuilds every module once in all, and no other module's code changes. Which of the two the runtime's
|
||||
decoder does today was not read for this amendment (*What is not decided here*).
|
||||
- **An acting rule's fields.** The seat's definition is where ADR 0656 has an acting part declare what it acts on. A
|
||||
seat's definition gains one optional field `acts`, with three fields of its own: `step`, one of `take-in`,
|
||||
`validate`, `check`, `build`, `compose`, `grant` and `place`; `on`, either `every` (every module) or a `language`
|
||||
naming the language of the modules it acts on, matched against what the manifest says its language is, as the
|
||||
indexer's language map matches today; and `bound`, how long an entry waits in that step for the acting part's new
|
||||
version (*An acting part's new version acts first*, below, gives each step's default). The definition format's own
|
||||
schema (design 26) gains the field, and the format stays 1. The indexer reads it into the catalog graph, the assigner
|
||||
into edges, and the checking program from the revision view. **Its cost in mesh-sdk:** the seat-definition reader in
|
||||
mesh-sdk's runtime refuses a definition with a field it does not know or a format other than 1, so a reader built
|
||||
before the field refuses every definition that carries `acts`, and a refused definition blocks new claims of that
|
||||
seat only (ADR 0636 §3), never what runs. The runtime therefore learns `acts`, which rebuilds every module once
|
||||
(ADR 0656, Consequences); that is the same rebuild the fingerprint handover makes, so the milestone rebuilds every
|
||||
module once in all, and no other module's code changes. A definition carrying `acts` reaches only readers built with
|
||||
that runtime: the seat definitions that gain it are members of milestone G's group, and every reader is rebuilt in
|
||||
the same delivery.
|
||||
- **The fingerprint handover.** The node-engine starts each process, a service or a container alike, with the
|
||||
environment value `MESH_FINGERPRINT`, the fingerprint of the want it applies; mesh-sdk's runtime reads it once at the
|
||||
process's start and holds it as the process's own build (ADR 0656). A process started with no value says `own build
|
||||
@@ -647,11 +701,17 @@ ADR 0656 leaves how each part is built to this design, under issue 1921; these f
|
||||
builds the named program at them, runs it in the run step (ADR 0448 §2) with the input the ask carries as a file,
|
||||
and writes the program's output and its exit on the build module's step key named by the ask's id (ADR 0525 §6). It
|
||||
is an accepted ask of the seat, not a request verb, because it is a long job pulled where there is capacity, never
|
||||
a call to a named node. The seat definition of `node-build-go` in `mesh-delivery-contracts` names it; the checking
|
||||
program, the acting parts and the composer a check builds from a change all run through it (ADR 0656, ADR 0644).
|
||||
a call to a named node. Only the checker's account may publish `run`, and the checker's account reads only the step
|
||||
keys of its own asks' ids (ADR 0363 §2), so no other part can have a program run or read its verdict. The seat
|
||||
definition of `node-build-go` in `mesh-delivery-contracts` names it; the checking program, the acting parts and the
|
||||
composer a check builds from a change all run through it (ADR 0656, ADR 0644). A program is built once per
|
||||
fingerprint: the build is the builder's build of that fingerprint (ADR 0498 §1), kept like any build and reused by
|
||||
every later ask naming it, so two checks of changes that leave the checking program unchanged ask one build.
|
||||
- **The first tier's own bound.** A check's first tier has 20 minutes for all its builds together, inside the check's
|
||||
one-hour bound of the state table and the checker's step bound (ADR 0639 §5); an acting part not built within it is
|
||||
one the first tier cannot build, and the check fails naming it (ADR 0656).
|
||||
one the first tier cannot build, and the check fails naming it (ADR 0656). The verdict tells two cases apart: `waiting
|
||||
for a build node` when no build node of the language took the ask within the bound, and `did not build` when one
|
||||
took it and the build failed, so the operator knows whether to free a build node or fix the change.
|
||||
|
||||
### Choices this design makes under ADR 0656
|
||||
|
||||
@@ -660,26 +720,36 @@ ADR 0656 decides the direction and leaves every choice made in working it out to
|
||||
|
||||
| Choice | Why |
|
||||
|---|---|
|
||||
| Both graphs kept as objects in the indexer's and the assigner's existing `objects` sections, each with a cap | both parts are the foundation, whose new kept data goes on the old sections so neither waits on the bus module to start (ADR 0619 §1, §2) |
|
||||
| ADR 0603 §2's keys and five past values stay until the milestone's delivery | what runs keeps reading them until the parts that read revisions are delivered in the same milestone |
|
||||
| A revision kept while a delivery record pins it, removed only on the gate's `freed` | a trace must read every revision it moved between; a timer or a read of the gate's state would drop one still pointed at, or cross the seam (ADR 0596) |
|
||||
| Both graphs kept as objects in an `objects` section in the old form, each with a cap of 512 MiB | both parts are the foundation, whose new kept data goes on the old sections so neither waits on the bus module to start (ADR 0619 §1, §2); the caps hold the estimated 90 days with room |
|
||||
| ADR 0603 §2's keys and the wants kept written beside the revisions until milestone H | a reverted indexer and assigner then read current state and send no node back to an older fingerprint, with nothing to convert at a rollback |
|
||||
| A revision removed when no record pins it and it is not current, pins counted per revision | a trace must read every revision it moved between, and a revision neither pinned nor current is read by nobody; counting pins keeps a revision two records share |
|
||||
| The indexer and the assigner hear `pinned`, `freed` and `heads-replaced` through durable consumers | an event said while either was down is applied when it comes back, so no revision leaks and none is dropped early |
|
||||
| Records kept 90 days by default, the gate's setting `record-retention`, the ledger capped at 128 MiB | the traces asked so far went back weeks; 90 days at an estimated 0.6 MiB a day is about 54 MiB |
|
||||
| A store passing 80 % of its cap said as `filling` and raised; a full cap refused as `full`, naming the part | the operator hears of a store filling while there is time, and a full store stops work loudly instead of dropping what a trace needs |
|
||||
| A candidate's graphs kept apart and dropped on `heads-replaced` | a candidate must never write wants or be read by a running part, and its graphs mean nothing once its heads are gone |
|
||||
| The verbs `revision`, `entry` and `difference` on the two seats | each half of the view, and the difference, is served by its one owner through its seat, never read from its state |
|
||||
| The step events, their fields and their subjects | every outcome the delivery record keeps reaches it as the event of the part that did it, with the revisions and the fingerprint that tie it to the trace (research 085, Findings 7) |
|
||||
| A first tier of only the changed acting parts, bounded at 20 minutes | an ordinary change pays nothing more; a bound turns a build that never ends into a named failure inside the check's hour |
|
||||
| The build seat's ask `run` | the program is a long job pulled where capacity is, run in the sandbox every check already uses (ADR 0448 §2) |
|
||||
| The node-engine reads its want and the catalog half, never the assignment half | the want is the one record a node reads; the assignment half would have each node read every node's placements |
|
||||
| Capability changes said as the node-engine seat's event `capabilities-changed` | the assigner follows an event instead of reading node records across the seam (ADR 0596) |
|
||||
| The step events, their fields and their subjects, with the node in the subject of every event a node publishes | every outcome reaches the delivery record as the event of the part that did it (research 085, Findings 7), and a node's account can be granted only its own node's subjects (ADR 0363 §2) |
|
||||
| A first tier of only the changed acting parts, bounded at 20 minutes, its verdict telling `waiting for a build node` from `did not build` | an ordinary change pays nothing more; a bound turns a build that never ends into a named failure, and the two words tell the operator which act frees it |
|
||||
| The build seat's ask `run`, published only by the checker's account, its step keys read only by it | the program is a long job pulled where capacity is, run in the sandbox every check already uses (ADR 0448 §2), and no other part can have a program run or read its verdict |
|
||||
| A program built once per fingerprint and reused | a check that leaves the checking program unchanged costs no build |
|
||||
| Every program built from a change run with no network and no bus account | a change not yet merged is not trusted, and the sandbox already keeps the logins outside (ADR 0448 §2, §4) |
|
||||
| A removed or altered rule of the checking program, and an added acting rule, named in the verdict and the Approve ask | either widens or narrows what judges or acts on every module, so the operator sees it before approving |
|
||||
| The rule names of the trunk's and the heads' checking programs compared by the running checker, outside the sandbox; a removed, altered, added or widened rule named in the verdict and the Approve ask | the comparison is made from the sources by a part the change did not build, so a program that drops a rule and hides it is still named; a rule widens or narrows what judges or acts on every module, so the operator sees it before approving |
|
||||
| A rule matching a module with no holder for its step held by name, and its check failed | a rule nobody serves would otherwise pass in silence |
|
||||
| Each step's wait held by the part that does the step, read by `assigner_waits` and steered by `assigner_release` and `builder_build_again` | the part that does the step already holds its state; the tools are those ADR 0603 §11 has |
|
||||
| The acting rule's field `acts` with `step` and `on` | the steps and the language match are what the indexer's map and the checker's cases held in code (research 085, Findings 2) |
|
||||
| Each step's wait held by the part that does the step, with its own read and release tools and the events `wait-held` and `wait-ended` | the part that does the step already holds its state, and the watchman and the record follow every wait by events alone |
|
||||
| The bound per step in the acting rule, with a default per step | the time a step's new version needs is the acting part's to know, not another module's |
|
||||
| A build module's wait ends on the agreed toolchain naming the new build module | the agreed toolchain is what a fingerprint takes (ADR 0584 §1), so before it names the new build module no module could be built once by it |
|
||||
| The running indexer makes a catalog graph revision with the named indexer's entry | the newer indexer can then be wanted and granted, so a revision waiting for it is never stuck behind it |
|
||||
| The acting rule's field `acts` with `step`, `on` and `bound`, the definition format staying 1 | the steps and the language match are what the indexer's map and the checker's cases held in code (research 085, Findings 2); the reader refuses an unknown field, so the runtime learns it in the one rebuild the milestone makes |
|
||||
| The fingerprint handed as `MESH_FINGERPRINT` at a process's start | one value every runtime reads before anything else, a service and a container alike |
|
||||
| The delivery record's consumer, end, node away and wake, switch with `merges` and `turns` kept current, retention and tools | a restart must lose and double nothing; a node asleep must not hold a delivery open; a gate rolled back must find current state and ask no approved group again |
|
||||
| The delivery record's consumer, held and failed outcomes, end and `record-ended`, the finding `record-open`, node away and wake, switch with `merges` and `turns` kept current, and tools | a restart must lose and double nothing; a reader sees why an entry stands still; a node asleep must not hold a delivery open; a gate rolled back must find current state and ask no approved group again |
|
||||
| A small fix's own record | a small fix is a milestone of one issue (ADR 0493 §3) |
|
||||
| An Approve given held while its heads stand (issue 1972) | the operator approved those heads; a check of them asked again changes nothing they approved (ADR 0441 §1, ADR 0548 §8) |
|
||||
| The milestone events on a subject of their own | a waiter on one member's pull request otherwise wakes on every member's |
|
||||
| The issue tracker's link kinds to a decision and a research effort, and the knowledge base's link from a decision to its milestone | the trace from research to the running build is then links all the way, with no text match (research 085, Findings 7; ADR 0493 §4) |
|
||||
| Two view tools in mesh-sdk's runtime bundle beside ADR 0636 §7's, and `node_process_builds` | every part's view and every process's own build is read and steered by a tool, as the seat list already is |
|
||||
| Two view tools in mesh-sdk's runtime bundle beside ADR 0636 §7's, the finding `view-waits` after five minutes, and `node_process_builds` | every part's view and every process's own build is read and steered by a tool, and a part waiting for the view is raised on the bound the seat list's readers keep |
|
||||
| Every drop and release tool writes the hand-act log | a hand act that changes what the mesh runs or keeps is recorded with who did it and why, as every hand act is (seat `mesh-hand-acts`) |
|
||||
|
||||
Each choice is checked by the tests its section names; the review by architectural domain judges them.
|
||||
|
||||
@@ -691,7 +761,9 @@ and the assignment graph revisions; an entry taken in, built, checked, composed,
|
||||
entry's fingerprint and its node. The gate's delivery record is built from them. The seat's event comes first where
|
||||
the parts follow it through a seat (ADR 0656); a holder's own event stays under its own subject, declared in its own
|
||||
manifest's `streams` and published on `mesh.stream.<module>.event.<event>` (ADR 0363 §1, §2). A seat's event is
|
||||
declared in its definition and its holder's manifest claims the seat.
|
||||
declared in its definition and its holder's manifest claims the seat. **An event a node publishes carries the node in
|
||||
its subject**, and the grants part grants each node-engine's account only its own node's subjects, so one node cannot
|
||||
say another runs a build (ADR 0363 §2); the gate's events are granted to the gate's account alone.
|
||||
|
||||
| Step | Event | Owner: the seat, then the module | Subject | Declared in |
|
||||
|---|---|---|---|---|
|
||||
@@ -702,54 +774,63 @@ declared in its definition and its holder's manifest claims the seat.
|
||||
| an entry built | `build.ended` | the builder's own | `mesh.stream.mesh-delivery-builder.event.build.ended` | the builder's manifest |
|
||||
| an entry checked | `checked` | `mesh-delivery-checker`, the checker | `mesh.seat.mesh-delivery-checker.event.checked` | the seat's definition in `mesh-delivery-contracts` |
|
||||
| an entry wanted | `wanted` | `mesh-wants`, the assigner | `mesh.seat.mesh-wants.event.wanted` | the seat's definition in `mesh-placement-contracts` |
|
||||
| an entry composed, and running healthy | `composed`, `running` | `node-engine`, the node-engine on each node | `mesh.seat.node-engine.event.composed`, `.running` | the seat's definition in `mesh-contracts` |
|
||||
| a record pins or frees a revision; a candidate's heads replaced | `pinned`, `freed`, `heads-replaced` | `mesh-delivery`, the gate | `mesh.seat.mesh-delivery.event.<event>` | the seat's definition in `mesh-delivery-contracts` |
|
||||
| an entry composed, and running healthy | `composed`, `running` | `node-engine`, the node-engine on each node | `mesh.seat.node-engine.event.composed.<node>`, `.running.<node>` | the seat's definition in `mesh-contracts` |
|
||||
| a node's capabilities changed | `capabilities-changed` | `node-engine`, the node-engine on that node | `mesh.seat.node-engine.event.capabilities-changed.<node>` | the same |
|
||||
| a wait held, and ended | `wait-held`, `wait-ended` (step, acting part, its version, the entry, since when; for an end, how: ran, released) | each holder: `mesh-wants` for the assigner, `mesh-grants` for the grants part, `node-engine` for the node-engine (with `.<node>`), the builder's own stream | `mesh.seat.<seat>.event.wait-held`, `.wait-ended`; `mesh.stream.mesh-delivery-builder.event.wait-held`, `.wait-ended` | each seat's definition; the builder's manifest |
|
||||
| a store filling, or full | `filling`, `full` | `mesh-catalog`, `mesh-wants`, `mesh-delivery` | `mesh.seat.<seat>.event.filling`, `.full` | each seat's definition |
|
||||
| a record pins or frees a revision; a candidate's heads replaced; a record ended | `pinned`, `freed`, `heads-replaced`, `record-ended` | `mesh-delivery`, the gate | `mesh.seat.mesh-delivery.event.<event>` | the seat's definition in `mesh-delivery-contracts` |
|
||||
| a milestone's ask asked, withdrawn and answered | `milestone.asked`, `milestone.withdrawn`, `milestone.answered` | `mesh-delivery`, the gate | `mesh.seat.mesh-delivery.event.milestone.<milestone>.<event>`, apart from each delivery's `transition` | the same |
|
||||
|
||||
The events, their fields, their subjects and which are a seat's are this design's choices: a seat's event where
|
||||
other parts follow the step through the seat, a holder's own event where only the delivery record hears it, so that
|
||||
nothing reads another module's bus state (ADR 0596). How it is checked: each seat
|
||||
definition's conformance fixtures name the subject of every event it gains, and a case of the holder's whole-module
|
||||
test matches an event it publishes against them, as for every seat (design 26); the gate's whole-module test hears
|
||||
each row through its durable consumer, with exactly the fields this section gives it.
|
||||
nothing reads another module's bus state (ADR 0596). The builder's waits go on its own stream because the builder
|
||||
holds no seat of its own; the watchman and the gate follow them there. How it is checked: each seat definition's
|
||||
conformance fixtures name the subject of every event it gains, and a case of the holder's whole-module test matches an
|
||||
event it publishes against them, as for every seat (design 26); the gate's whole-module test hears each row through
|
||||
its durable consumer, with exactly the fields this section gives it; a `running` event published by one node's account
|
||||
on another node's subject is refused by the bus.
|
||||
|
||||
### Their tools
|
||||
|
||||
| Line | The assigner | The indexer |
|
||||
|---|---|---|
|
||||
| read everything it holds | `assigner_revision` (one assignment graph revision whole, with the revisions of its inputs), `assigner_entry` (one entry, with the seat rule that gave each edge), `assigner_difference` (a change's difference), `assigner_waits` (*Order without a person*), `assigner_candidate_graphs` (every candidate's graphs: its heads, its revisions, since when) | `indexer_catalog_revision` (one catalog graph revision), `indexer_candidate_graphs` (every candidate's catalog half) |
|
||||
| do by hand what it does itself | `assigner_recompute` (compute a revision again from its named inputs and compare it with the one kept) | — |
|
||||
| recover without help | `assigner_drop_candidate_graph` (drop a candidate's graphs whose gate event never came) | `indexer_drop_candidate_graph` (the same for its half) |
|
||||
| read everything it holds | `assigner_revision` (one assignment graph revision whole, with the revisions of its inputs), `assigner_revisions` (every kept revision with what pins it, and the store's fill against its cap), `assigner_entry` (one entry, with the seat rule that gave each edge), `assigner_difference` (a change's difference), `assigner_waits` (*Order without a person*), `assigner_candidate_graphs` (every candidate's graphs: its heads, its revisions, since when), `assigner_consumer` (its consumer of the gate's events: the last applied, the waiting) | `indexer_catalog_revision` (one catalog graph revision), `indexer_catalog_revisions` (every kept revision with what pins it, and the store's fill against its cap), `indexer_candidate_graphs` (every candidate's catalog half), `indexer_consumer` (the same as the assigner's) |
|
||||
| do by hand what it does itself | `assigner_recompute` (compute a revision again from its named inputs and compare it with the one kept) | `indexer_recompute` (compute a catalog graph revision again from its source revision and compare it with the one kept) |
|
||||
| recover without help | `assigner_drop_candidate_graph` (drop a candidate's graphs whose gate event never came), `assigner_release` (*Order without a person*) | `indexer_drop_candidate_graph` (the same for its half) |
|
||||
| one seat, many tools | `mesh-wants`: `revision`, `entry`, `difference` | `mesh-catalog`: `revision`, beside `seat-definitions` |
|
||||
|
||||
Every drop and release tool writes its act, who did it and why, in the hand-act log of the seat `mesh-hand-acts`.
|
||||
Beside ADR 0636 §7's two tools in mesh-sdk's runtime bundle, which read a reader's seat list and make it read the
|
||||
list again, the bundle gains two for the view: one reads which view revision a part holds and what it waits for, the
|
||||
other, granted as ADR 0636 §7's second is, makes it read the view again now. A tool of the node-engine,
|
||||
`node_process_builds`, reads the build each process was started with. The tools answer the four lines every module's
|
||||
tools answer (design 26), so that every state these parts keep is read and every act they do is steered by a tool.
|
||||
list again, the bundle gains two for the view: `waits`, which reads which view revision a part holds and what it
|
||||
waits for and since when, and one, granted as ADR 0636 §7's second is, that makes it read the view again now. A tool
|
||||
of the node-engine, `node_process_builds`, reads the build each process was started with. The tools answer the four
|
||||
lines every module's tools answer (design 26), so that every state these parts keep is read and every act they do is
|
||||
steered by a tool.
|
||||
|
||||
**How it is checked.** a revision of the assignment graph computed again from its named inputs
|
||||
equals the one kept (unit, assigner); a fixture change with a new fingerprint and an
|
||||
empty difference is refused, naming its module (unit, assigner), and a group's preview before its merge is its
|
||||
difference (live) ; a pull request that adds a seat and a module using it is validated by
|
||||
the indexer's candidate pass and checked by the checker with the same definitions (whole), and a search of the
|
||||
readers' code finds no compiled seat list (live) ; a part started while its node's want
|
||||
differs from what runs reports the build it was started with (whole, node-engine). Unit
|
||||
(assigner): one revision of about 120 modules on four nodes stays under the bus's value limit, and of
|
||||
the view the assigner reads only the catalog half; unit (indexer), a catalog graph revision holds one entry per module
|
||||
of its source revision. Whole (indexer): a source revision taken in gives one catalog graph revision kept as objects
|
||||
in the old `objects` section within the cap its manifest declares; the manifest validator refuses the indexer's or
|
||||
the assigner's manifest that declares them in the new form. Whole (indexer, assigner): a revision a delivery record
|
||||
pins is not removed, and one is removed on the gate's `freed`; a candidate's graphs are dropped on `heads-replaced`;
|
||||
for a candidate's heads both `revision` verbs answer, the assigner's half named by its own revision and naming its
|
||||
inputs; a placement change with no merge gives a new assignment half on the same catalog half, whose difference moves
|
||||
only the module placed, and a part takes that pair as its view; after its first view a part acts on a seat event
|
||||
without asking a verb again; a running part does not act on a candidate's view; with the indexer stopped, a waiting
|
||||
part keeps running what it runs, and a part asking the view for a new revision says it waits, naming it, and acts once
|
||||
the indexer is back. Whole (assigner): a pull request's graph leaves every node's want unchanged; a placement-only
|
||||
revision moves the want of the module it places; the builder, the grants part and the node-engine read their entries
|
||||
only through the seat `mesh-wants`'s verbs and events; the tools of the table answer, and both view tools answer.
|
||||
Live: a search of the readers' code finds no read of another module's bus state; an old node-engine that wakes takes
|
||||
its new build in a form it reads.
|
||||
**How it is checked.** Unit (assigner): a revision of the assignment graph computed again from its named inputs
|
||||
equals the one kept; a fixture change with a new fingerprint and an empty difference is refused, naming its module;
|
||||
one revision of about 120 modules on four nodes stays under the bus's value limit; of the view the assigner reads only
|
||||
the catalog half. Unit (indexer): a catalog graph revision holds one entry per module of its source revision. Whole
|
||||
(indexer): a source revision taken in gives one catalog graph revision kept as objects in an `objects` section in the
|
||||
old form within the cap its manifest declares; the manifest validator refuses the indexer's or the assigner's manifest
|
||||
that declares them in the new form. Whole (indexer, assigner): a revision a delivery record pins is not removed; one
|
||||
two records pin stays until both free it; one neither pinned nor current is removed; a `freed` said while the part
|
||||
was stopped is applied after its restart; a candidate's graphs are dropped on `heads-replaced`; a store past 80 % says
|
||||
`filling` and raises `store-filling`, and a full one says `full` and refuses its next revision naming itself; for a
|
||||
candidate's heads both `revision` verbs answer, the assigner's half named by its own revision and naming its inputs; a
|
||||
placement change with no merge, and a `capabilities-changed`, each give a new assignment half on the same catalog half,
|
||||
whose difference moves only the module concerned, and a part takes that pair as its view; after its first view a part
|
||||
acts on a seat event without asking a verb again; a running part does not act on a candidate's view; a pull request
|
||||
that adds a seat and a module using it is validated by the indexer's candidate pass and checked by the checker with
|
||||
the same definitions; the tools of the table answer and the drop tools write the hand-act log. Whole (assigner): a
|
||||
pull request's graph leaves every node's want unchanged; a placement-only revision moves the want of the module it
|
||||
places; the builder and the grants part read their entries only through the seat `mesh-wants`'s verbs and events, and
|
||||
the node-engine reads its want and the catalog half and never the assignment half. Whole (node-engine): a part started
|
||||
while its node's want differs from what runs reports the build it was started with. Live: a search of the readers'
|
||||
code finds none of the reads the revision view replaces, each by name: the indexer's read of the checker's previews,
|
||||
the checker's watch of the indexer's `candidates.<try id>`, the forge bridge's read of the gate's `merges`, the
|
||||
checker's validator request with no seat definitions, and a seat list compiled into the node-engine, the checker, the
|
||||
builder or the grants part; an old node-engine that wakes takes its new build in a form it reads.
|
||||
|
||||
## Order without a person
|
||||
|
||||
@@ -777,7 +858,7 @@ per module and node from the keys:
|
||||
### An acting part's new version acts first, a wait with a bound
|
||||
|
||||
*ADR 0656, which supersedes ADR 0646; ADR 0603 §1 to §4, §8, §11, ADR 0614 §1, §3, §6, ADR 0633
|
||||
§1, ADR 0539 §7, ADR 0584 §1.*
|
||||
§1, ADR 0539 §7, ADR 0584 §1, §2, ADR 0564 §2.*
|
||||
|
||||
From research 085's milestone. A seat's definition may carry a rule, the step its holder acts in and the modules it
|
||||
acts on, and a holder of such a seat is an **acting part** (ADR 0656): the indexer taking in and validating, the
|
||||
@@ -789,20 +870,26 @@ names go, since every new acting part needed code changes elsewhere (research 08
|
||||
- **The rule becomes edges between versions.** In the assignment graph the assigner gives an edge from the acting
|
||||
part's version to each version its rule names, and no part names another module in its code to order by (ADR 0656).
|
||||
- **Within a revision the new version acts first, a wait with a bound.** The entries an acting part acts on wait for
|
||||
its new version in its own step, with a bound (ADR 0656), the part's own as ADR 0603 §8 has every wait. For a build
|
||||
module the entry waits until the agreed toolchain (ADR 0584 §1) names the new build module, so the module's
|
||||
fingerprint names the new recipe and it is built once, by the new one: a module changed with its build module is no
|
||||
longer built with the running recipe and again later, and a build module's edge, a trigger no want waited on,
|
||||
becomes this wait (ADR 0656, which changes ADR 0603 §1, §3 and ADR 0614 §1, §6). ADR 0603 §3's fingerprint naming
|
||||
the agreed toolchain stands.
|
||||
- **A failed or late new version holds its modules, and a condition names it.** When the new version fails, or does
|
||||
not run within its bound, the entries waiting for it stay held, the modules stay on their running builds, and the
|
||||
watchman raises a condition naming the acting part; an entry moves on only once the new version runs, or a tool
|
||||
releases it (ADR 0656: its new versions act first within a bound), and the condition clears when the wait ends. The
|
||||
operator sees each stuck acting part as one condition, and `assigner_release` steers it. Going on with the running
|
||||
version instead would build or check a change with a part it replaced, the cause of the failures of research 085,
|
||||
Findings 4; stopping the whole delivery would hold modules the failed part does not act on (the operator, 2026-11-06
|
||||
17:0x).
|
||||
its new version in its own step, with the bound its rule's `bound` gives (ADR 0656), the part's own as ADR 0603 §8
|
||||
has every wait. When a rule names none, the step's default holds: 60 minutes for building (a build module's own
|
||||
build and its spread to a majority of build nodes), 30 for composing (a node-engine's apply on every node it runs
|
||||
on), 10 for granting and placing (a write of one part), and the first tier's 20 for checking. A module changed with
|
||||
its build module is no longer built with the running recipe and again later, and a build module's edge, a trigger no
|
||||
want waited on, becomes this wait (ADR 0656, which changes ADR 0603 §1, §3 and ADR 0614 §1, §6).
|
||||
- **A build module's wait ends on the agreed toolchain.** For building, an entry waits until the agreed toolchain of
|
||||
its language (ADR 0584 §1) names the new build module, never merely until the new build module runs on one node: a
|
||||
fingerprint names the agreed toolchain (ADR 0603 §3), so only then is the module built once, by the new one. A build
|
||||
node still on the old build module builds nothing of that language until it reports the agreed one (ADR 0584 §2).
|
||||
Every other step's wait ends when the acting part's new version runs healthy, as the node-engine seat's `running`
|
||||
event says.
|
||||
- **A failed or late new version holds its modules, and a condition names it.** When the new version fails, or its
|
||||
wait passes its bound, the entries waiting for it stay held, the modules stay on their running builds, and the
|
||||
holder says `wait-held` past its bound; the watchman writes the finding `acting-part-late` naming the acting part,
|
||||
its step and since when, and the condition keeper raises it (ADR 0564 §2). An entry moves on only once the new
|
||||
version runs, or its holder's release tool releases it; either way the holder says `wait-ended`, and the finding and
|
||||
the condition clear. The operator sees each stuck acting part as one condition. Going on with the running version
|
||||
instead would build or check a change with a part it replaced, the cause of the failures of research 085, Findings
|
||||
4; stopping the whole delivery would hold modules the failed part does not act on (the operator, 2026-11-06 17:0x).
|
||||
- **A wait holds only within its step, and skips the holder's own inputs** (ADR 0656). An entry waits only for its
|
||||
own step's holders, so two acting parts that act on each other in different steps (the indexer taking in the
|
||||
checker, the checker checking the indexer) form no cycle. Within a step a holder's own change is its first act, and
|
||||
@@ -812,35 +899,50 @@ names go, since every new acting part needed code changes elsewhere (research 08
|
||||
- **The check refuses a cycle among the waits within one step** (ADR 0656, which changes ADR 0603 §2's refusal of a
|
||||
cycle), counted beside the edges ADR 0614 §3 and §6 list; a cycle through an acting part's edges across two steps, or
|
||||
through a holder's own inputs, is none.
|
||||
- **The indexer's own steps have no wait.** Taking in and validating stay as *Taken in by the indexer it names* has
|
||||
them: a revision is taken in only by the indexer it names, which judges its own change at its start, and no build
|
||||
waits on which indexer judged it (ADR 0603 §4, as ADR 0633 §1 changes it).
|
||||
- **The indexer's own steps have no wait, and a newer indexer is reached.** Taking in and validating stay as *Taken in
|
||||
by the indexer it names* has them: a revision is taken in only by the indexer it names, which judges its own change
|
||||
at its start, and no build waits on which indexer judged it (ADR 0603 §4, as ADR 0633 §1 changes it). So that the
|
||||
named indexer can start at all, the running indexer makes, for a merged revision naming a newer indexer, a catalog
|
||||
graph revision holding that indexer's own entry, read from its manifest at the merge, and nothing else of the
|
||||
revision; the assigner wants it and the grants part grants it like any module, and once it runs it takes the revision
|
||||
in whole. Without that, a revision waiting for its indexer would wait for good.
|
||||
- **A rule with no holder is no silent pass.** An entry a rule matches with no holder for its step is held by the
|
||||
assigner, naming the missing holder as the hold's reason, and the check fails naming it.
|
||||
- **An acting rule grants nothing.** A holder's bus grants come from the grants part as today (ADR 0539 §7). An
|
||||
acting rule changes what a part acts on across every module it matches, so the operator's Approve ask of a change
|
||||
names any acting rule it adds.
|
||||
- **Each step's wait is its own part's**, so that each wait has one owner that already holds that step's state. Building: the builder's
|
||||
build-key wait; placing and wanting: the assigner's hold; granting: the grants part's; composing: the node-engine's;
|
||||
checking: the check's first tier (*The check on the change's own acting parts*, below). A wait ends when the acting
|
||||
part's new version runs healthy, as the node-engine seat's `running` event says.
|
||||
- **Read and steered by the parts' own tools.** The assigner's `assigner_waits` reads each wait: its entry, its step,
|
||||
the seat rule that gave it, the acting part's version it waits for and since when; `assigner_release` and
|
||||
`builder_build_again` steer them, as ADR 0603 §11 has them.
|
||||
- **How it is checked.** a fixture seat declaring a rule, with a fixture holder, gets its edges
|
||||
with no code change elsewhere (whole, assigner), and a search of the delivery parts' code finds no other module's
|
||||
name (live) ; a fixture group changing the shared contracts and the build module that
|
||||
builds them is delivered, the contracts built by the running build module first and the rest by the new one (whole,
|
||||
assigner and builder), and a cycle among waits within one step is refused (unit, graph) ; a fixture build module whose new build fails, and one that does not run within its bound, each leave
|
||||
their modules on their running builds and raise the condition naming it, which clears when the wait ends (whole,
|
||||
assigner and builder). Whole (assigner, builder): a module with no
|
||||
holder for its step is held by name, and the check of a change bringing it fails naming the missing holder;
|
||||
`assigner_release` moves a held entry on; a group changing the indexer and a module is taken in by the new indexer
|
||||
with no build waiting on it; each step's wait ends on the acting part's new version running healthy as the
|
||||
node-engine reports it, and `assigner_waits` reads each wait with its step, seat rule, version and since when.
|
||||
Unit (graph): an acting part acting on itself, two acting parts acting on each other in different steps, and a
|
||||
cycle through a build module's edge each pass the cycle check, each new version first in its own step. Unit
|
||||
(assigner): the Approve ask of a change that adds an acting rule names the rule.
|
||||
names any acting rule it adds, and any it widens: a `step`, an `on` or a longer `bound` that now matches more
|
||||
modules or holds them longer is named like an added rule.
|
||||
- **Each step's wait is its own part's, read and released by its own tools.** The part that does a step holds its
|
||||
wait, so each wait has one owner that already holds that step's state, and says `wait-held` and `wait-ended` (*What
|
||||
each step says*) with the step, the acting part, its version, the entry and since when:
|
||||
|
||||
| Step | Holder | Reads its waits | Releases one |
|
||||
|---|---|---|---|
|
||||
| building | the builder, on its build key | `builder_waits` | `builder_release` (build the entry with the running build module), beside `builder_build_again` (ADR 0603 §11) |
|
||||
| placing and wanting | the assigner, on its hold | `assigner_waits` | `assigner_release` (ADR 0603 §11) |
|
||||
| granting | the grants part | `grants_waits` | `grants_release` |
|
||||
| composing | the node-engine on each node: the assigner names in a want the node-engine version that want waits for, and the node-engine applies it only once it runs that version, keeping what it runs | `node_waits` | `node_release` |
|
||||
| checking | the check's first tier | `checker_first_tier` | its ask-again (*The check on the change's own acting parts*) |
|
||||
|
||||
Each release writes the hand-act log of the seat `mesh-hand-acts`, with who released and why.
|
||||
- **How it is checked.** Whole (assigner): a fixture seat declaring a rule, with a fixture holder, gets its edges with
|
||||
no code change elsewhere. Whole (assigner, builder, three build nodes): a group changing the shared contracts and the
|
||||
build module that builds them, the new build module updated on the first build node first, builds no module with the
|
||||
new build module while one node of three runs it, builds the contracts with the running build module, and once the
|
||||
second node reports it and the agreed toolchain names it, builds each other module once, by the new one; the third
|
||||
node builds nothing of the language until it reports the agreed version. Whole (assigner, builder, grants part,
|
||||
node-engine): a fixture acting part whose new version fails, and one whose wait passes its bound, each leave their
|
||||
modules on their running builds, say `wait-held`, and raise `acting-part-late` naming it; each holder's release tool
|
||||
moves a held entry on, says `wait-ended` and writes the hand-act log, and the condition clears; a wait ends on its
|
||||
own when the new version runs; each holder's read tool lists its waits with step, acting part, version and since
|
||||
when; a rule's `bound` overrides the step's default. Whole (indexer, assigner): a merged revision naming a newer
|
||||
indexer gives a catalog graph revision holding that indexer's entry; the new indexer is wanted and granted, starts,
|
||||
and takes the revision in, with no build waiting on which indexer judged it. Whole (assigner): a module with no
|
||||
holder for its step is held by name, and the check of a change bringing it fails naming the missing holder. Unit
|
||||
(graph): an acting part acting on itself, two acting parts acting on each other in different steps, and a cycle
|
||||
through a build module's edge each pass the cycle check, each new version first in its own step; a cycle among
|
||||
waits within one step is refused. Unit (assigner): the Approve ask of a change that adds an acting rule, and of one
|
||||
that widens one, names the rule. Live: a search of the delivery parts' code finds no other module's name.
|
||||
|
||||
The planner's edges (*built by*, *SDK before its users*, *verb before caller*, *version skew*) and its one
|
||||
default, the node-engine before the controller, ordered the tiers of a plan until release 6 (ADR 0419 §3 to
|
||||
@@ -1039,22 +1141,25 @@ From its delivery, a check is this:
|
||||
### The check on the change's own acting parts
|
||||
|
||||
*ADR 0656, which supersedes ADR 0648, ADR 0644; ADR 0448 §2, §4, ADR 0391 §1, ADR 0603 §10, ADR 0614 §7, ADR 0633
|
||||
§6, ADR 0636 §4, ADR 0639 §5.*
|
||||
§6, ADR 0636 §4, ADR 0639 §5, ADR 0498 §1.*
|
||||
|
||||
From research 085's milestone. ADR 0603 §10 and ADR 0614 §7 let a check pass while the part that would build or
|
||||
check the change never ran: 7 of 24 failures since 2026-11-01 (research 085, Findings 4). The acting parts a change alters,
|
||||
and the checking program, the rules every check applies, are built from the change's heads and check it; the running
|
||||
versions never check in their place, and a check fails, naming the part, when one cannot be built or run (ADR 0656).
|
||||
check the change never ran: 7 of 24 failures since 2026-11-01 (research 085, Findings 4). The acting parts a change
|
||||
alters, and the checking program, the rules every check applies, are built from the change's heads and check it; the
|
||||
running versions never check in their place, and a check fails, naming the part, when one cannot be built or run
|
||||
(ADR 0656).
|
||||
|
||||
- **Two tiers on the change's assignment graph.** The first tier builds, at the change's heads, only the acting parts
|
||||
whose fingerprint in the change's assignment graph differs from the running one and which are to act on a module
|
||||
the check acts on; a change to an ordinary module asks no first-tier build, since building every acting part for
|
||||
every check would make an ordinary change pay for builds that change nothing. The
|
||||
second tier runs the check's levels with those programs and with the revision view of the change's heads
|
||||
(ADR 0656). This keeps ADR 0603 §10's building of changed build modules first and widens it to every acting part.
|
||||
every check would make an ordinary change pay for builds that change nothing. The second tier runs the check's
|
||||
levels with those programs and with the revision view of the change's heads (ADR 0656). This keeps ADR 0603 §10's
|
||||
building of changed build modules first and widens it to every acting part.
|
||||
- **The judging rules are a checking program built from the change.** Every check builds its checking program from
|
||||
the change's heads and runs it with the revision view as its input; when it cannot be built or run, the check
|
||||
fails naming it, and the running checker's own rules never judge in its place (ADR 0656).
|
||||
fails naming it, and the running checker's own rules never judge in its place (ADR 0656). It is built once per
|
||||
fingerprint and reused (ADR 0498 §1): checks whose heads leave the checking program unchanged ask one build between
|
||||
them.
|
||||
- **Every program built from a change runs only in the build seat's sandbox.** The acting parts the first tier builds
|
||||
and the checking program run in the run step, with no network (ADR 0448 §2) and no bus account, the logins staying
|
||||
outside (ADR 0448 §4), through the seat `node-build-go`'s ask `run` (*What ADR 0656 leaves to this design*), as
|
||||
@@ -1065,9 +1170,12 @@ versions never check in their place, and a check fails, naming the part, when on
|
||||
manifest (ADR 0656, which changes ADR 0603 §10 and ADR 0614 §7), and ADR 0614 §7's reason, a changed build module
|
||||
invoking a verb no running holder serves, is one reason the first tier cannot run an acting part: the check fails
|
||||
naming the build module and the verb. An acting part not built within the first tier's bound of 20 minutes is one
|
||||
it cannot build.
|
||||
- **A change that alters or removes a rule of the checking program is named**, in its verdict and in the operator's
|
||||
Approve ask.
|
||||
it cannot build, and the verdict says `waiting for a build node` or `did not build`.
|
||||
- **A change to a rule of the checking program is named, by a part it did not build.** Each checking program
|
||||
declares its rules by name in its source. The running checker, outside the sandbox, reads the rule names from the
|
||||
trunk's sources and from the heads' and compares them; every rule removed, added or altered (its source changed) is
|
||||
named in the verdict and in the operator's Approve ask. The program built from the change is never asked which rules
|
||||
it has, so a program that drops a rule and hides it is still named.
|
||||
- **ADR 0633 §6 stays, beside the change's own validator.** Whether the running parts can take the change in is
|
||||
still checked with the trunk's manifest validator, built from the trunk (ADR 0633 §6); the change's own validator,
|
||||
built in the first tier, judges the change's manifests besides (ADR 0656). A change fails if either refuses it.
|
||||
@@ -1077,23 +1185,27 @@ versions never check in their place, and a check fails, naming the part, when on
|
||||
the members' heads and hands it to the manifest validator and the composer (ADR 0644, ADR 0636 §4 with its insight
|
||||
of 2026-11-06).
|
||||
- **Its tools.** The checker's read of a check names the checking program's build that judged it, its fingerprint and
|
||||
the heads it was built from; `checker_first_tier` lists a check's first-tier builds, each with its acting part, its
|
||||
fingerprint and its outcome, and asks one of them again. Asking a whole check again stays the checker's existing
|
||||
ask-again.
|
||||
- **What it costs.** A check of a change to an acting part costs one build per changed acting part, within the checker's step bound (ADR 0639 §5); an ordinary change costs nothing more; a group's
|
||||
check costs one build of its checking program.
|
||||
- **How it is checked.** A fixture change whose acting part does not build, and one whose checking
|
||||
program does not run, each fail their check, naming the part (whole, checker). In the checker's
|
||||
whole-module integration test: a checking program that builds but does not run fails
|
||||
naming it; a change that breaks a rule of the checking program fails its own check; a change that removes a rule
|
||||
passes, and its verdict and the ask name the removal; a fixture checking program that tries to reach the bus or
|
||||
the network fails; a fixture build module invoking a verb no running holder serves fails naming it and the verb; a
|
||||
change to an ordinary module asks no first-tier build; a group that changes the assigner's placing is checked with
|
||||
its own assigner; a fixture indexer change whose manifest the trunk's validator refuses fails its check, even when
|
||||
its own validator passes it; a fixture group whose heads add a seat has that seat in the list both the validator and
|
||||
the composer receive; the check's read names the checking program's build and heads; `checker_first_tier` lists a
|
||||
check's first-tier builds and asks one again; the changed checker asks one check of a fixture group end to end.
|
||||
Live: the registry group passes its one check with its own checker, validator and composer.
|
||||
the heads it was built from, and the rules named changed; `checker_first_tier` lists a check's first-tier builds,
|
||||
each with its acting part, its fingerprint and its outcome (`built`, `waiting for a build node`, `did not build`),
|
||||
and asks one of them again. Asking a whole check again stays the checker's existing ask-again.
|
||||
- **What it costs.** A check of a change to an acting part costs one build per changed acting part, within the
|
||||
checker's step bound (ADR 0639 §5); an ordinary change costs nothing more; a checking program costs one build per
|
||||
fingerprint, shared by every check that uses it.
|
||||
- **How it is checked.** In the checker's whole-module integration test: a fixture change whose acting part does not
|
||||
build, and one whose checking program does not run, each fail their check, naming the part; a checking program that
|
||||
builds but does not run fails naming it; a first-tier ask no build node takes within the bound says `waiting for a
|
||||
build node`, and one that fails says `did not build`; a change that breaks a rule of the checking program fails its
|
||||
own check; a change that removes a rule passes, and its verdict and the ask name the removal, also when the
|
||||
program built from the change hides it; a fixture checking program that tries to reach the bus or the network
|
||||
fails; a `run` ask published from an account other than the checker's is refused by the bus, and the checker's
|
||||
account cannot read another account's step key; a fixture build module invoking a verb no running holder serves
|
||||
fails naming it and the verb; a change to an ordinary module asks no first-tier build; two ordinary checks with the
|
||||
same checking program ask one build of it; a group that changes the assigner's placing is checked with its own
|
||||
assigner; a fixture indexer change whose manifest the trunk's validator refuses fails its check, even when its own
|
||||
validator passes it; a fixture group whose heads add a seat has that seat in the list both the validator and the
|
||||
composer receive; the check's read names the checking program's build, heads and changed rules; `checker_first_tier`
|
||||
lists a check's first-tier builds and asks one again; the changed checker asks one check of a fixture group end to
|
||||
end. Live: the registry group passes its one check with its own checker, validator and composer.
|
||||
|
||||
### A try: a delivery group's check at exact commits
|
||||
|
||||
@@ -1651,9 +1763,9 @@ assignments bucket is kept equal to it by the holder until ADR 0547's third mile
|
||||
| placement candidate | while a proposal is open: one node's placement as the proposal lays it, which that node composes in shadow and answers | the assigner | the seat's state `candidates` |
|
||||
| assignment | until ADR 0547's third milestone: the module and node, pinned or not, ended or not, written by `assign` and `unassign` after an approved placement change, so that it equals the placement (ADR 0567) | the controller, called by the holder | `mesh-controller_assignments` |
|
||||
| rollout | read-only from release 6: each plan of releases 1 to 5, its tiers, the builds it carried and the assignments it changed | nobody from release 6 | `mesh-controller_rollouts` |
|
||||
| catalog graph revision | from research 085's milestone: every module as its manifest declares it at one source revision, with the seats' acting rules (ADR 0656), kept while a delivery record pins it | the indexer | objects in its manifest's existing `objects` section (ADR 0619 §2) |
|
||||
| assignment graph revision | from research 085's milestone: every module version on a node at one revision, its edges, and the revisions of its inputs (ADR 0656), kept while a delivery record pins it | the assigner | objects in its manifest's existing `objects` section (ADR 0619 §2), served by the seat `mesh-wants` |
|
||||
| delivery record | from research 085's milestone: one milestone's delivery, its group's state, its trace and what happened to each entry on each node (ADR 0656), kept for good unless the gate's manifest sets a retention | the gate | a ledger instance of the gate's (ADR 0595, ADR 0597) |
|
||||
| catalog graph revision | from research 085's milestone: every module as its manifest declares it at one source revision, with the seats' acting rules (ADR 0656), kept while a delivery record pins it or it is current | the indexer | objects in an `objects` section in the old form (ADR 0619 §2), capped at 512 MiB |
|
||||
| assignment graph revision | from research 085's milestone: every module version on a node at one revision, its edges, and the revisions of its inputs (ADR 0656), kept while a delivery record pins it or it is current | the assigner | objects in an `objects` section in the old form (ADR 0619 §2), capped at 512 MiB, served by the seat `mesh-wants` |
|
||||
| delivery record | from research 085's milestone: one milestone's delivery, its group's state, its trace and what happened to each entry on each node (ADR 0656), kept 90 days by default (the gate's setting `record-retention`) | the gate | a ledger instance of the gate's (ADR 0595, ADR 0597) |
|
||||
|
||||
Beside the chain, on the bus too: deliveries and groups (the gate's `deliveries` and `groups`, ADR 0239 §37), one
|
||||
key per open pull request (the gate), and the grants part's state (`user-list`, the memberships it last
|
||||
@@ -1719,25 +1831,26 @@ From research 085's milestone the seat gains:
|
||||
| Verb or event | Answers or does |
|
||||
|---|---|
|
||||
| `groups` with a group | that group's members, which the forge bridge reads in place of the gate's `merges` state (ADR 0656) |
|
||||
| `review` | records a reviewer's verdict at the full head it judged, as ADR 0493 §5 has it; once it runs, the line in a pull request's description is read no more (ADR 0496 §3, issue 1782). Whether the reviewer is taken from the caller's bus account and a review by the head's author refused is another question, waiting on issue 1782 |
|
||||
| milestone events | the one Approve ask per milestone (ADR 0493 §9 as ADR 0496 §2 changes it, issue 1783), held until it is answered, or withdrawn by a new head and asked again (ADR 0441 §1); said on a subject of their own, while each delivery's transitions stay as they are, so a waiter on one member's pull request wakes only on that member's `transition` |
|
||||
| `pinned`, `freed`, `heads-replaced` | the events by which the indexer and the assigner keep or drop graph revisions (*The delivery record*) |
|
||||
| `milestone.asked`, `milestone.withdrawn`, `milestone.answered` | the one Approve ask per milestone (ADR 0493 §9 as ADR 0496 §2 changes it, issue 1783), held until it is answered, or withdrawn by a new head and asked again (ADR 0441 §1); said on `mesh.seat.mesh-delivery.event.milestone.<milestone>.<event>`, apart from each delivery's `transition`, which stays as it is, so a waiter on one member's pull request wakes only on that member's `transition` |
|
||||
| `pinned`, `freed`, `heads-replaced` | the events by which the indexer and the assigner keep or drop graph revisions, said only from the gate's account (*The delivery record*) |
|
||||
| `record-ended`, `filling`, `full` | a delivery record ended; the ledger past 80 % of its cap; the ledger full (*The delivery record*) |
|
||||
|
||||
**The seats `mesh-catalog` and `mesh-wants`** gain, from research 085's milestone, `revision` on each (the two halves
|
||||
of the revision view, ADR 0656), and `entry` and `difference` on `mesh-wants` (ADR 0656), with the events of *What
|
||||
each step says*.
|
||||
|
||||
**Links of the trace.** The review is recorded by the verb `review` (ADR 0493 §5), and the trace's other links are
|
||||
this design's choices under ADR 0656, so that one call traces research to the running build
|
||||
**Links of the trace.** A review stays the line in a pull request's description, as ADR 0496 §3 has it, until issue
|
||||
1782 builds the review verb and settles who may review and its grant, outside milestone G. The trace's links are this
|
||||
design's choices under ADR 0656, so that one call traces research to the running build
|
||||
with no text match (research 085, Findings 7). The issue tracker gains link kinds from an issue to the decision and to the research effort
|
||||
it carries, made by a tool call and never by text, as ADR 0493 §4 has every link made; the knowledge base gains a
|
||||
typed link from a decision to the milestone of the issue tracker that builds it, made by a tool call, which joins the
|
||||
link kinds of its link-fits rule (design 55), beside the `became` link a research effort gets at its graduation
|
||||
(playbook 02). How it is checked: whole (gate), the verdict is read from the verb, not the description; one ask per milestone, withdrawn by a new head;
|
||||
(playbook 02). How it is checked: whole (gate), one ask per milestone, withdrawn by a new head;
|
||||
a waiter on one member's pull request wakes only on that member's transition. Whole (issue tracker, knowledge base):
|
||||
an issue linked to a decision and to a research effort reads both back; a decision linked to its milestone reads it
|
||||
back. Live: research 085's milestone's record reads back research 085 to its decisions, its milestone, its issues,
|
||||
its pull requests and their reviews with no text match.
|
||||
back. Live: research 085's milestone's record reads back research 085 to its decisions, its milestone, its issues and
|
||||
its pull requests with no text match.
|
||||
|
||||
**The status view's tools** read the keys and change nothing: `assigner_wants`, `assigner_want`,
|
||||
`assigner_differences` and `node_haves`, beside the indexer's and the builder's. Its events are `delivered`,
|
||||
@@ -1926,9 +2039,10 @@ list:
|
||||
edges with no code change elsewhere, and a search of the delivery parts' code finds no other module's name.
|
||||
28. **Waits stay within their step.** A cycle among waits within one step is refused; an acting part acting on
|
||||
itself, and two acting parts acting on each other in different steps, pass.
|
||||
29. **A failed acting part leaves the mesh on what runs.** A build module whose new build fails, and one that does not
|
||||
run within its bound, each leave the modules it builds on their running builds and raise the condition naming
|
||||
it, which clears when the wait ends.
|
||||
29. **A failed acting part leaves the mesh on what runs.** A build module whose new build fails, and one whose wait
|
||||
passes its bound, each leave the modules it builds on their running builds, say `wait-held`, and raise
|
||||
`acting-part-late` naming it; the holder's release tool moves an entry on, says `wait-ended` and writes the
|
||||
hand-act log, and the condition clears.
|
||||
30. **A change is delivered as its difference.** A group that changes the indexer, the checker and a module that
|
||||
needs both is delivered with no delivery ahead of it, each acting part's new version first in its own step, a
|
||||
node asleep throughout catching up when it wakes; a fixture change with a new fingerprint and an empty difference
|
||||
@@ -1936,42 +2050,62 @@ list:
|
||||
31. **The registry group checks itself.** The registry group passes its one check with its own checker, validator and
|
||||
composer.
|
||||
32. **One view.** A pull request adding a seat and a module using it is validated by the indexer's candidate pass and
|
||||
checked by the checker with the same definitions, and a search of the readers' code finds no compiled seat list.
|
||||
checked by the checker with the same definitions, and a search of the readers' code finds none of the reads the
|
||||
revision view replaces, each by name (*Their tools*).
|
||||
33. **Two graphs, one source.** A revision of the assignment graph computed again from its named inputs equals the one
|
||||
kept.
|
||||
34. **One record traces a delivery.** Stopping and restarting the gate in the middle of a delivery leaves the record
|
||||
complete, with no outcome counted twice, and one call traces an issue of the registry milestone to each node's
|
||||
running build, also after six later merges; a group approved before the switch to the records is not asked again.
|
||||
35. **The trace is links.** Research 085's milestone reads back from research 085 to its decisions, its milestone,
|
||||
its issues, its pull requests and their reviews with no text match.
|
||||
36. **The milestone can be undone.** A revert of research 085's milestone passes its check under the milestone's own
|
||||
checker (research 085, Direction, One milestone).
|
||||
its issues and its pull requests with no text match.
|
||||
36. **The milestone can be undone, whole.** In a whole-module fixture of the indexer and the assigner, milestone G's
|
||||
versions take in revisions and write wants, then the versions of before it are started in their place: they read
|
||||
the per-module keys the new ones kept writing, compute the same wants, and write no want naming a fingerprint
|
||||
older than the one each node runs; the gate rolled back the same way asks no approved group again.
|
||||
37. **Nothing is delivered ahead.** Research 085's milestone is delivered with no part delivered ahead of it, read
|
||||
from its delivery record (ADR 0656, How it is checked).
|
||||
38. **A newer indexer is reached.** A merged revision naming a newer indexer gives, from the running indexer, a catalog
|
||||
graph revision holding that indexer's entry; the new indexer is wanted, granted, started, and takes the revision in.
|
||||
39. **Revisions are kept, and stores say their fill.** A revision pinned by two records stays until both free it, one
|
||||
neither pinned nor current goes, a `freed` said while its holder was stopped is applied after its restart, a record
|
||||
past its 90 days is removed and frees its revisions, a store past 80 % raises `store-filling`, and a full one
|
||||
refuses loudly, naming the part.
|
||||
40. **Nobody says what is not theirs.** A `running` event on another node's subject, a `freed` from an account other
|
||||
than the gate's, and a `run` ask from an account other than the checker's are each refused by the bus.
|
||||
41. **A checking program is built once and judged from outside.** Two ordinary checks with the same checking program
|
||||
ask one build of it; a change whose checking program drops a rule and hides it is still named in its verdict and
|
||||
Approve ask.
|
||||
|
||||
Each change ADR 0656 makes in an earlier record, and its test:
|
||||
|
||||
38. **The want comes from the assignment graph** (ADR 0571 §8). A node-engine's want is written only from a trunk
|
||||
42. **The want comes from the assignment graph** (ADR 0571 §8). A node-engine's want is written only from a trunk
|
||||
revision's assignment graph: a pull request's graph leaves every node's want unchanged, and a placement-only
|
||||
revision moves the want of the module it places (whole, assigner).
|
||||
39. **A module changed with its build module is built once, by the new one** (ADR 0603 §1, §3, ADR 0614 §1, §6). A
|
||||
group changing the shared contracts and the build module that builds them is delivered, the contracts built by
|
||||
the running build module first and the rest by the new one, each module built once, with no build by the running
|
||||
recipe for a module the new build module builds (whole, assigner and builder).
|
||||
40. **The graph is kept per revision** (ADR 0603 §2). A source revision taken in gives one catalog graph revision and
|
||||
its assignment graph revision, kept as objects in the old `objects` sections, and a revision a delivery record
|
||||
pins is not removed; no key per module with five past values is written (whole, indexer and assigner).
|
||||
41. **The tiers are a view of the difference** (ADR 0603 §6). The view's tiers of a group equal those read off its
|
||||
43. **A module changed with its build module is built once, by the new one** (ADR 0603 §1, §3, ADR 0614 §1, §6). With
|
||||
three build nodes and the new build module updated on the first node first, a group changing the shared contracts
|
||||
and the build module that builds them builds nothing with the new build module while one node of three runs it,
|
||||
builds the contracts with the running one, and once the agreed toolchain names the new build module (ADR 0584
|
||||
§1) builds each other module once, by it, with no build by the running recipe of a module the new build module
|
||||
builds; the third node builds nothing of the language until it reports the agreed version (whole, assigner and
|
||||
builder).
|
||||
44. **The graph is kept per revision** (ADR 0603 §2). A source revision taken in gives one catalog graph revision and
|
||||
its assignment graph revision, kept as objects in an `objects` section in the old form, and a revision a delivery
|
||||
record pins is not removed; every part reads the revisions, and the per-module keys are written only for a
|
||||
rollback, read by no part of milestone G (whole, indexer and assigner).
|
||||
45. **The tiers are a view of the difference** (ADR 0603 §6). The view's tiers of a group equal those read off its
|
||||
difference by `difference`, with no other source read (whole, view and assigner).
|
||||
42. **A check fails by name** (ADR 0603 §10, ADR 0614 §7). A fixture change whose acting part does not build, one
|
||||
46. **A check fails by name** (ADR 0603 §10, ADR 0614 §7). A fixture change whose acting part does not build, one
|
||||
whose checking program does not run, and one whose build module invokes a verb no running holder serves, each fail
|
||||
their check naming the part, and no module of them is composed from its manifest (whole, checker).
|
||||
43. **A part waits for the revision view** (ADR 0636 §1, §4). With the indexer stopped, the checker, the builder and
|
||||
the grants part each keep running what they run, say they wait, naming the revision, and act once it is back; a
|
||||
candidate's heads are read by the indexer's candidate pass and by no running part (whole).
|
||||
44. **A process reports its handed build** (ADR 0639 §7). A part started while its node's want differs from what runs
|
||||
47. **A part waits for the revision view** (ADR 0636 §1, §4). With the indexer stopped, then with the assigner stopped,
|
||||
and on a cold control-node whose parts all start with no view, the checker, the builder and the grants part each
|
||||
keep running what they run, answer `waits` with the revision and since when, write `view-waits` after five minutes,
|
||||
and act once the view is back, clearing it; the node-engine waits only for the catalog half; a candidate's heads
|
||||
are read by the indexer's candidate pass and by no running part (whole).
|
||||
48. **A process reports its handed build** (ADR 0639 §7). A part started while its node's want differs from what runs
|
||||
reports the build it was started with, and `node_process_builds` reads it (whole, node-engine).
|
||||
45. **The forge bridge reads a group from the gate's verb** (ADR 0633 §4, §5). The forge bridge sets the group on each
|
||||
49. **The forge bridge reads a group from the gate's verb** (ADR 0633 §4, §5). The forge bridge sets the group on each
|
||||
merged message and publishes a group's end again from the seat `mesh-delivery`'s verb `groups`, and its account
|
||||
holds no read of the gate's `merges` state, so a read of it is refused (whole, forge bridge).
|
||||
|
||||
@@ -2022,12 +2156,12 @@ Each change ADR 0656 makes in an earlier record, and its test:
|
||||
module names and its cases for a change to the manifest validator and to the Go build module (ADR 0656); a build
|
||||
module's edge as a trigger, with the extra build per recipe change (ADR 0603 §3, as ADR 0656 changes it); composing
|
||||
from manifests a module whose changed build module the check cannot run (ADR 0603 §10 and ADR 0614 §7, as ADR 0656
|
||||
changes them); the module graph's one key per module with five past values (ADR 0603 §2, as ADR 0656 changes it);
|
||||
the tiers worked out from five live sources (ADR 0603 §6, as ADR 0656 changes it); a seat list compiled into a
|
||||
part, and every read of another module's bus state the revision view replaces (ADR 0656); the gate's `merges` and
|
||||
`turns` as its own state, carried into the delivery records and kept current beside them until a later change
|
||||
removes them; and the review line in a pull request's description, once the verb `review` runs
|
||||
(ADR 0496 §3).
|
||||
changes them); the module graph's one key per module with five past values as what parts read (ADR 0603 §2, as
|
||||
ADR 0656 changes it); the tiers worked out from five live sources (ADR 0603 §6, as ADR 0656 changes it); a seat
|
||||
list compiled into a part, and every read of another module's bus state the revision view replaces (ADR 0656); and
|
||||
the gate's `merges` and `turns` as its own state, carried into the delivery records.
|
||||
- At milestone H's delivery: the writing of ADR 0603 §2's per-module keys beside the revisions, and of the gate's
|
||||
`merges` and `turns` beside the records, kept until then only so that a rollback of milestone G reads current state.
|
||||
|
||||
## Milestones
|
||||
|
||||
@@ -2078,7 +2212,8 @@ release reports the controller's code lines against research 063's baseline (acc
|
||||
| L6 | Provisioning leaves the controller (ADR 0570): every provision is one key of the seat `mesh-provisioner`, held by mesh-provisioner, holding a reference and never a value, and each placed module's provisioning plan a key of its state `plans`, both composed from placement, the wants and the manifests on change events; each provider acts once all a provision depends on is provided; the assigner moves a want only once its build's provisions are provided; a provision no want needs is retiring, and its account or credential is removed only on the operator's Approve, its data never; the vault mints each provision's secret sealed to the consumer's and the provider's node, and the consumer's node-engine writes it; a wait for a person is a provision's state, which the watchman reads; bus permissions stay with the grants part (ADR 0349, ADR 0230, ADR 0547 §11) | — | mesh-sdk, the node-engine (`mesh-host`), mesh-tools (the tool runner's provisioner client), mesh-catalog (mesh-provisioner, the vault, the provisioner client, postgres, keycloak, gitea, route-adapter), mesh-delivery (assigner, watchman) | 1954 |
|
||||
| L7 | History and records leave the controller (ADR 0571): the builder keeps its build log, one entry at a build's start and one at its end, from which build history and durations are read and the module mesh-catalog asks the builds it missed; the artifact sweep is the seat `mesh-artifact-sweep`, held by artifact-store-tools beside the artifact store, its keep set from the store's own listing, the wants and the build log, sweeping at each build's end from the lease write and recording each deletion in the hand-act log; disk readings are disk-load's own state on every node; who holds which seat is the state `seat-holders` of the seat `mesh-placement` (now `mesh-module-assigner`), and tools are found by the tool runners' announcements; what a node runs is its want and its have; the grants part writes `grants.<module>.<fingerprint>` and keeps memberships in its own state; root-free is a probe of the self-check; no manifest but the controller's reads, invokes or consumes `mesh-controller`, but a named list kept to the lease write, so the lease write's check passes (ADR 0189, ADR 0547 §11, ADR 0549 §6) | — | mesh-sdk, mesh-controller (its pin only), mesh-delivery (builder, indexer, assigner, grants part, view), mesh-catalog (artifact-store-tools, disk-load, the backup seat's holder, mounts, nfs-server, minio, mesh-watcher, the messenger, the self-check, the module mesh-catalog, docker), mesh-tools (the tool runner) | 1955 |
|
||||
| B0 | The bootstrap delivery: a delivery group's check runs a checking program built from the group's own heads in the build seat's sandbox, and hands the manifest validator and the composer the heads' one seat list; it brings no seat definition, so the running checker checks it (ADR 0644) | 26 needs it | mesh-delivery (checker), mesh-catalog (mesh-build-go), mesh-delivery-contracts (the seat `node-build-go`'s ask `run`) | 1921 |
|
||||
| G | Two graphs and one revision view: the catalog graph and the assignment graph kept per revision, a change delivered as its graph difference, the acting parts' rules on their seats as bounded waits that hold their modules when the new version fails, the check on the change's own acting parts, the revision view and each process's own build, the gate's delivery record, and the trace's links (ADR 0656); the registry milestone's reviewed heads are joined to its group as members | 26 to 45 | mesh-sdk (the runtime: the fingerprint, the view, the definition reader), mesh-contracts and the domains' contracts modules (`acts`, the new verbs and events), mesh-delivery (indexer, assigner, checker, builder, grants part, gate's view, forge bridge), mesh-catalog (the gate, the build modules, mesh-issues, mesh-knowledge), the node-engine (`mesh-host`), hq | 1966 (with the registry milestone's heads), 1961, 1660, 1962, 1972, 1721, 1783, 1785, 1794, 1791, 1373, 1782 |
|
||||
| G | Two graphs and one revision view: the catalog graph and the assignment graph kept per revision, a change delivered as its graph difference, the acting parts' rules on their seats as bounded waits that hold their modules when the new version fails, the check on the change's own acting parts, the revision view and each process's own build, the gate's delivery record, and the trace's links (ADR 0656); the registry milestone's reviewed heads are joined to its group as members | 26 to 49 | mesh-sdk (the runtime: the fingerprint, the view, the definition reader), mesh-contracts and the domains' contracts modules (`acts`, the new verbs and events), mesh-delivery (indexer, assigner, checker, builder, grants part, gate's view, forge bridge), mesh-catalog (the gate, the build modules, mesh-issues, mesh-knowledge), the node-engine (`mesh-host`), hq | 1966 (with the registry milestone's heads), 1961, 1660, 1962, 1972, 1721, 1783, 1785, 1794, 1791, 1373 |
|
||||
| H | The old keys go: once milestone G has run for one record retention (90 days) with no rollback, the indexer stops writing ADR 0603 §2's per-module keys, the assigner reads none, and the gate stops writing `merges` and `turns` (*Two graphs, one source of truth*, *Rolled back*) | — | mesh-delivery (indexer, assigner), mesh-catalog (the gate) | 1921 |
|
||||
|
||||
An issue is in one row only (ADR 0493 §2): where a row named an issue another row names too, the last row keeps it and the
|
||||
earlier row says so in words (the operator, 2026-10-26). Milestone M1 makes each row a record of the issue tracker
|
||||
@@ -2155,11 +2290,12 @@ order inside one milestone, for this one case (ADR 0644).
|
||||
|
||||
## What is not decided here
|
||||
|
||||
- Whether mesh-sdk's runtime decoder refuses an unread field in a seat definition today was not read; it decides
|
||||
whether `acts` alone would rebuild every module.
|
||||
- Who may review a change, and the review verb's grant: issue 1782, outside milestone G; until it is built the review
|
||||
stays the line in a pull request's description (ADR 0496 §3).
|
||||
- What a process started by a node-engine that hands no fingerprint does beyond saying `own build unknown`, for a part
|
||||
other than the indexer.
|
||||
- Whether a catalog graph revision has a size bound of its own, as the assignment graph revision's is tested.
|
||||
- The caps' and the growth's numbers are estimates (*Two graphs, one source of truth*); the fill tools read the real
|
||||
ones once milestone G runs, and a cap is changed in its manifest.
|
||||
|
||||
- How long the checker's stream `checks` keeps its events (*A try*, above).
|
||||
- Who is granted `checker_try` and the take-in hand tools: the operator's grants, outside this design.
|
||||
|
||||
Reference in New Issue
Block a user