diff --git a/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md b/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md index 6f44c187..6109f620 100644 --- a/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md +++ b/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md @@ -1655,8 +1655,8 @@ list: assigner and gate wanted; a module delivered during milestone G keeps its fingerprint while they wait; no want goes to a fingerprint older than the trunk's; the operator is asked again only for an ask raised after the restore point. A revert whose restore point is missing is held, naming it. Proved with the real builds of the indexer, the - assigner and the gate from before milestone G, not fixtures (whole, checker, gate, assigner, indexer, node-engine, - backup holder, bus module). + assigner and the gate from before milestone G, not fixtures, started by their fingerprints in the artifact store + (whole, in `mesh-host`: checker, gate, assigner, indexer, node-engine, backup holder, bus module; design 47 G §405). 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 diff --git a/03-DESIGN/01-to-be/47-milestones/G-1-pipelines-registration-and-steps.md b/03-DESIGN/01-to-be/47-milestones/G-1-pipelines-registration-and-steps.md index ee12ec53..d9fe3b09 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-1-pipelines-registration-and-steps.md +++ b/03-DESIGN/01-to-be/47-milestones/G-1-pipelines-registration-and-steps.md @@ -235,7 +235,7 @@ check and deliver milestone G itself (ADR 0667 §2); each of them says so in a l and an `approval` step is not; a module with no integration tests shows `nothing to run`, and a `required` unit-test step on a module with no tests holds its delivery; a bypassed step is said; a runner restarted mid-step hears the step's end and finishes the pipeline; two runners writing one pipeline key, one loses by compare-and-set; a test step's - counts are in `step-ended` and a repository over budget is named in `pipeline-ended`. Whole (Go build module): `steps` + counts are in `step-ended` and a catalog module over budget is named in `pipeline-ended` (§419). Whole (Go build module): `steps` answers the steps of a fixture artifact, a `step` ask ends with `step-ended` on its own node's subject, one on another node's subject is refused by the bus, and a build module restarted mid-step finishes it. Unit (manifest validator): a manifest naming a status is refused. Tests 65, 66, 73 and 88. diff --git a/03-DESIGN/01-to-be/47-milestones/G-2-pipelines-sizes-checks-and-tools.md b/03-DESIGN/01-to-be/47-milestones/G-2-pipelines-sizes-checks-and-tools.md index da1581bb..a0587c2c 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-2-pipelines-sizes-checks-and-tools.md +++ b/03-DESIGN/01-to-be/47-milestones/G-2-pipelines-sizes-checks-and-tools.md @@ -235,7 +235,7 @@ and an estimated 2 mesh-sdk publishes a day, each rebuilding about 120 artifacts | the watchman, the keeper | `machine-away`, `machine-back` (§389); `findings-asked` (§390) | the seats' definitions | 90 days; 7 days | 16 MiB each | | the runner | `aged`: three step-log sequences (§330) | old `state` section | never deleted | bytes | | the teller | `widens-said` (§335) | the template `state` | until the branch is unwatched | a few KiB; the template's | -| each build module | `steps` (§326) | the template `state` | one key per artifact, dropped by `steps` with `drop` | under 1 MiB; the template's | +| each build module | `detected-steps` (§326, §414) | the template `state` | one key per artifact, dropped by `steps` with `drop` | under 1 MiB; the template's | | the indexer | `registrations` and its stream `registration-history` | old `state` and `streams` sections | the life of the mesh, never derived again | 64 MiB (*A module's registration*) | | the indexer | catalog graph revisions, per watched branch | objects in the old form (ADR 0619 §2) | while a record pins it or it is its branch's current | 512 MiB, as *Two graphs, one source of truth*; a second watched branch on a few modules adds a few MiB | | the gate | `source`: one key per watched branch | its old `state` section, as today | 64 revisions of each key; a branch's key deleted when `registration-changed` says the last registration watching it unwatched it (`unwatch`) | a few KiB | @@ -344,7 +344,7 @@ step keys and the builder's build log, against the checker's last week (test 99) | §124 Each state's object store `-objects` through mesh-sdk's small package, sent objects readable by a standing grant derived from the catalog graph, and the package's two tools | one object store per state, granted to its owner; the sender's declared callers and consumers read what it sends (ADR 0666 §16); only its users import it, so nothing else is rebuilt | | §125 The `run` ask published by the runner's account and the indexer's; the verb `run` called by the sessions and the operator only | the steps and the validation run code from the change, in the sandbox only, and each asker reads only its own step keys (ADR 0363 §2); a run publishes tagged packages, so nothing else may ask one | | §126 The checker's step `check` becomes `pipeline`; `kept` starts empty | the runner is an acting part in the checker's place (ADR 0666 §19); a step's result is taken only from its seat holder (ADR 0666 §21), so no verdict of the checker's is taken in, at the cost of one round of every module's tests | -| §127 The field `callers` in a seat definition replaces the holders' trusted `callers`, a missing field admitting the holder roles and the operator only | the record makes the definition the grants part's one source (ADR 0666 §20); a field left out must open nothing | +| §127 The field `callers` in a seat definition replaces the holders' trusted `callers`, a missing field taking the default of the verb's `class` (§391) | the record makes the definition the grants part's one source (ADR 0666 §20); a field left out must open nothing | | §128 `widens` in `pipeline-ended`, computed by the running runner over every part serving a step, passed on by the teller | a widening is said and nothing refuses it (ADR 0666 §23, §26); a change must not compute its own | | §129 `merge-pull` judged from the forge module's own `failed-steps`, heard from `step-ended`, any run at the head's fingerprint counting unless a later rerun of that step passed, the protection read again on every `branch-moved` | the record has it judge from the events it consumes, never by a call, so a head merges while the runner is down (ADR 0666 §11, ADR 0596) | | §130 The new assigner before the new `merge-pull` and the runner, by `needs`, both switching on the first `registration-changed` | a merge with no Approve must never reach an assigner that writes wants without a pipeline (ADR 0667 §10) | diff --git a/03-DESIGN/01-to-be/47-milestones/G-3-delivery-record-and-graphs.md b/03-DESIGN/01-to-be/47-milestones/G-3-delivery-record-and-graphs.md index 67f0b389..b4ecce4d 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-3-delivery-record-and-graphs.md +++ b/03-DESIGN/01-to-be/47-milestones/G-3-delivery-record-and-graphs.md @@ -3,7 +3,7 @@ layer: to-be status: in-progress design: 47 milestone: G -updated: 2026-11-10 +updated: 2026-11-11 decisions: - "ADR 0666" - "ADR 0656" @@ -284,16 +284,17 @@ Findings 11). How each is kept, read and retained is this design's choice under must read every revision it moved between, and a revision neither pinned nor current is read by nobody. - §179 **An unchanged entry is stored once.** A revision is kept as its list of entries' digests, and each entry as an object of its own named by its digest, so an entry that two revisions share is stored once; an entry object is - removed when no kept revision lists it. Consecutive revisions differ by the few entries a delivery moves, so this + removed when no kept revision lists it and no want or running build names its fingerprint (§443). Consecutive revisions differ by the few entries a delivery moves, so this keeps the growth to what changes. It is chosen over a larger cap because whole revisions would grow with every revision whatever changed, and a cap would only delay the same fill. - §180 **The caps and the growth** (estimates, to be read from the fill tools once the milestone runs). A whole 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 + catalog graph revision's list of about 120 entries about 4 KiB, its entries, each carrying its manifest whole + (§443), about 15 KiB each. 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. A delivery moving 5 modules on four nodes adds about 20 assignment entries of about 1 KiB and a - list of about 15 KiB, and 5 catalog entries and a list of about 4 KiB: about 0.7 MiB a day of assignment graph and - 0.2 MiB of catalog graph, about 63 MiB and 18 MiB at the records' default retention of 90 days. The caps are 512 MiB + list of about 15 KiB, and 5 catalog entries of about 15 KiB and a list of about 4 KiB: about 0.7 MiB a day of assignment graph and + 1.6 MiB of catalog graph, about 63 MiB and 144 MiB at the records' default retention of 90 days. The caps are 512 MiB for each, many times the steady state. Placement-only and capability-only revisions are pinned by no record and go when they stop being current. - §181 **A store filling is said before it is full.** The indexer, the assigner and the gate each say their fill against diff --git a/03-DESIGN/01-to-be/47-milestones/G-4-revision-view-and-steps.md b/03-DESIGN/01-to-be/47-milestones/G-4-revision-view-and-steps.md index 08069af1..2a18de0b 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-4-revision-view-and-steps.md +++ b/03-DESIGN/01-to-be/47-milestones/G-4-revision-view-and-steps.md @@ -57,7 +57,8 @@ One file of milestone G's part of [design 47](../47-delivery-from-commit-to-deli 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). From G's delivery a running part acts on a revision of a watched branch as on a trunk revision, and a - candidate's view is read only by a run on request's steps and the indexer's candidate pass (ADR 0666 §6, §18). + candidate's view is read only by a run on request's steps, the grants part's `grants-for` (§441) and the indexer's + candidate pass (ADR 0666 §6, §18). - §196 **Every other reader of which modules exist reads the catalog half, in the same milestone.** From milestone G the indexer declares no state `modules` and serves neither its tool `indexer_read_modules` nor a view of it (*Reverted*, above), so every module that learns from it which modules exist moves in milestone G, not after: the watchman (its diff --git a/03-DESIGN/01-to-be/47-milestones/G-5-acting-parts-check-and-kept-data.md b/03-DESIGN/01-to-be/47-milestones/G-5-acting-parts-check-and-kept-data.md index 64ca5ec3..7a924046 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-5-acting-parts-check-and-kept-data.md +++ b/03-DESIGN/01-to-be/47-milestones/G-5-acting-parts-check-and-kept-data.md @@ -3,7 +3,7 @@ layer: to-be status: in-progress design: 47 milestone: G -updated: 2026-11-10 +updated: 2026-11-11 decisions: - "ADR 0667" - "ADR 0666" @@ -338,7 +338,7 @@ later change of a kept data's form, not as a case of this milestone. catch-up tool the newer manifest declares beside that kept data. A failed backup holds that module as any failed backup does. - §297 **A revert restores it before the reverted build starts.** When a want takes a module back across a change of a - kept data's `form`, the node agent applying it asks that seat's verb `restore` for the restore point of that module, + kept data's `form`, the node agent applying it stops the newer build, then asks that seat's verb `restore` (§405) for the restore point of that module, kept data and form, waits for the seat's event `restored`, and only then starts the reverted build. The node agent that restores is the one running when the revert starts. As every restore is, it is brought back beside the live data and never over it: the live kept data of the newer form is set aside under a name of its own, and only the operator diff --git a/03-DESIGN/01-to-be/47-milestones/G-6-verbs-and-retires.md b/03-DESIGN/01-to-be/47-milestones/G-6-verbs-and-retires.md index 8c9d0f91..45ceb2c4 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-6-verbs-and-retires.md +++ b/03-DESIGN/01-to-be/47-milestones/G-6-verbs-and-retires.md @@ -59,8 +59,8 @@ of each verb (ADR 0666 §7, §20, §25): | `run` | the run on request of one or more members, each a module at a named commit; delivers nothing | the sessions (the agents' bus identities the tool runner proves) and the operator, nothing else | | `start` | a delivering pipeline for a watched branch's head, by hand | the operator, the healers | | `show`, `list`, `stands`, `why-carried`, `kept` | one pipeline whole with its step log; the pipelines and runs of a module, a branch or a commit; what stands still; where a result was carried from; the kept results | any person, an agent session, the healers | -| `review` | a code review's result for a commit and fingerprint | the reviewers the definition names; refused from the commit's author | -| `rerun`, `accept`, `cancel`, `ask-again` | one step again; a failed `optional` step accepted with why; a pipeline ended, its asks dropped; a declined `approval` asked again | the operator, the healers (`accept` and `ask-again` the operator) | +| `review` | a code review's result for a commit and fingerprint | sessions; refused from the commit's author (§394) | +| `rerun`, `accept`, `cancel`, `ask-again` | one step again; a failed `optional` step accepted with why; a pipeline ended, its asks dropped; a declined `approval` asked again | the operator, the healers (`accept` and `ask-again` the operator; §391, §394) | §307 **The seat `mesh-catalog`** gains, from milestone G's delivery, `register`, `policy`, `watch`, `unwatch` and `registrations`, and the event `registration-changed` (*A module's registration*), and `catalog-revision` names its diff --git a/03-DESIGN/01-to-be/47-milestones/G-9-prepare-answers.md b/03-DESIGN/01-to-be/47-milestones/G-9-prepare-answers.md index d58280da..f7ff6c2f 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-9-prepare-answers.md +++ b/03-DESIGN/01-to-be/47-milestones/G-9-prepare-answers.md @@ -38,15 +38,17 @@ line says so.* - §391 **Every verb takes a default of callers by its class.** From the operator's answers of 2026-11-11 (02:13 CET, "Any declaring module"; 02:47 and 02:56 CET, "As proposed"), a verb's definition names its class in the field `class`, and a verb whose definition names no `callers` takes its class's default, which the seat-definition reader - applies and the manifest validator says per verb ("`.` takes the default of ``"): a `read`, the - class a verb names none of, takes `invokers`, `persons` and `sessions`, so every verb open today stays open; an - `act` (a new act that changes what the mesh does: registers, sets a policy, watches or unwatches a branch, - recovers) takes `operator` and `sessions`; a `warrant` (a verb that runs on the operator's warrant) takes `operator` - and carries the approval mark; `accept` is the operator's alone (§394). A verb that names `callers` keeps them, so - no verb is closed by §68 for lack of a list. Why: ADR 0666 §20 makes the definition the one source of caller - limits; the operator asked on 2026-11-11 why caller questions kept coming, and answered them as one rule (Q1, S3, - C3, D2's reads, Q18). How it is checked: unit (seat-definition reader), a table test with one row per class, and a - row for a verb with `callers` of its own; unit (manifest validator), the default each verb took is said. + applies and the manifest validator says per verb ("`.` takes the default of ``"): a `read` takes + `invokers`, `persons` and `sessions`; an `act` (a new act that changes what the mesh does: registers, sets a policy, + watches or unwatches a branch, recovers, restores) takes `operator` and `sessions`; a `warrant` (a verb that runs on + the operator's warrant) takes `operator` and carries the approval mark; `accept` is the operator's alone (§394). A + verb on main that names no class is a `read`, so every verb open today stays open; a verb G adds must name its + `class`, and the definition reader refuses one that does not. A verb that names `callers` keeps them, so no verb is + closed by §68 for lack of a list; §68, §127 and §306 point here. Why: ADR 0666 §20 makes the definition the one source + of caller limits; the operator asked on 2026-11-11 why caller questions kept coming, and answered them as one rule + (Q1, S3, C3, D2's reads, Q18). How it is checked: unit (seat-definition reader), a table test with one row per class, + a row for a verb with `callers` of its own, and a row refusing a verb G adds without `class`; unit (manifest + validator), the default each verb took is said. - §392 **A caller entry names its kind of name.** In `callers`, a holder role is written `seat:` and a module `module:`, beside `operator`, `healers`, `persons`, `sessions`, `invokers` and `holder:@same-node` (§336), since a name such as `mesh-grants` is both a seat and a module. Why: the design's choice (Q2). How it is @@ -63,21 +65,24 @@ line says so.* operator and the healers (§83, §40). Why: the operator, 2026-11-11 02:56 CET on Telegram, "As proposed" (S4, S10, C18, D2, D3, D4). How it is checked: whole (indexer, runner, operator-channel), a call from any other caller is refused by the bus; unit (definition reader), each verb's class and callers. -- §395 **An accepted kind naming no callers keeps today's grant.** `operator-channel`'s kinds `ask`, `cancel` and - `condition` keep the grant they have today, open to every asker, so the runner's approval (§37), the seed ask (§8) - and every other asker are not refused (§338). Why: the operator's intent, a verb open today stays open (Q18). How it - is checked: whole (operator-channel), an asker's `ask` is taken. +- §395 **An accepted kind naming no callers keeps today's grant.** `operator-channel`'s kinds `ask` and `condition` + keep the grant they have today, open to every asker, so the runner's approval (§37), the seed ask (§8) and every + other asker are not refused (§338); `cancel` stays limited to each asker's own subject (ADR 0259 §3). Why: the + operator's intent, a verb open today stays open (Q18). How it is checked: whole (operator-channel), an asker's `ask` + is taken and its `cancel` of another asker's ask is refused by the bus. ### The forms of a seat's definition - §396 **A dot only where no stream is named from the event; `keep`'s form.** An event whose definition names `keep` has no dot in its name, since its stream `SEAT__` is named from it; an event naming no `keep` stays on - its seat's family stream and may have a dot. `keep` is an object `{max-age-days, max-mib, last-per-subject}`, its age - 90 days and its cap 16 MiB unless it names others (§331). The seat `git`'s events take hyphens: `pull-updated`, - `pull-merged`, `pull-closed`, `forge-pull`, `forge-status`, `forge-delete` and `repo-writable` (§310), and `owed` is - kept on its seat stream 7 days and 64 MiB (§162). This amends §260. Why: the design's choice (Q3, Q4, S5, C1, C2). - How it is checked: unit (definition reader), a dotted event with `keep` refused, one without accepted, `keep`'s - defaults. + the shared stream EVENTS, its seat's family, kept 7 days, and may have a dot. `keep` is an object of three fields: + `max-age-days` (days; `0` is the one value for no age limit), `max-mib`, and `last-per-subject` (yes or no); unless + it names others its age is 90 days, its cap 16 MiB and `last-per-subject` no (§331). The seat `git`'s events take + hyphens: `pull-updated`, `pull-merged`, `pull-closed`, `forge-pull`, `forge-status`, `forge-delete` and + `repo-writable` (§310). The gate's `owed` is kept on its seat stream `SEAT_mesh-delivery_owed`, 7 days and 64 MiB + (§162), its one name. This amends §260. Why: the design's choice (Q3, Q4, S5, C1, C2). How it is checked: unit + (definition reader), a dotted event with `keep` refused, one without accepted, `keep`'s defaults and `0` read as no + age limit. - §397 **The forms of `subject`, `acts.on` and `bound`.** `subject` is the words after `mesh.seat..event.` with `` tokens, `` written out; `acts.on` is one string, `every`, a language, or `kind:image`; `bound` is a duration such as `30m`. Why: the design's choice (Q5). How it is checked: unit (definition reader), each form @@ -102,21 +107,33 @@ line says so.* field `held-since`, and no field `behind`. Why: the design's choice (Q14). How it is checked: the seat's fixtures. - §404 **The node-engine's events' bodies.** `capabilities-changed` carries the node record's stated capabilities whole and `at`; `composed` the module, the fingerprint and the composition's digest; `running` with `stopped` carries - `stopped: true` and no fingerprint (§365). Why: the design's choice (Q17). How it is checked: the seat's fixtures. + `stopped: true` and no fingerprint (§365), and mesh-sdk's `SeatsToPassOn` counts such a module as not running on that + node. Why: the design's choice (Q17). How it is checked: the seat's fixtures; unit (`SeatsToPassOn`), a row where a + `stopped` holder passes no seat. ### Kept data on the bus, restore points and the reader release - §405 **The bus module's restore points and node-backup's verbs.** The seat `mesh-broker` gains `snapshot-kept` and - `restore-kept`, their callers `holder:node-backup@same-node` (§337); the seat `node-backup`'s `now` and `restore` - gain `kept`, `form` and `fingerprint`, and say `ended.` and `restored.`, each keyed by the module, the - kept data, its form and the fingerprint; listing and discarding stay node-backup's `backed-up` and `discard-aside` - (§302), and so does `aside`, which sets a module's live kept data aside before a restore; `mesh-broker` serves - only `snapshot-kept` and `restore-kept`. Test 36's whole case lives in `mesh-host`. Why: the design's choice, one answer to three preparers (Q8, S9, - Q-H6, C19; lead-47's ruling, 2026-11-11). How it is checked: test 36; a call of `snapshot-kept` from another node's `node-backup` - holder is refused by the bus. + `restore-kept`, of class `act`, their callers `holder:node-backup@same-node` alone (§337): the bus module's account is + the one that moves bus data, so `restore-kept` sets the live kept data aside under a name of its own and then + restores the restore point beside it, with the argument `aside-only` it sets the live data aside and restores + nothing, and with the argument `discard-aside`, naming data set aside, it removes that data and restores nothing. + The seat `node-backup`'s `now`, `restore` and `aside` (class `act`, callers by §391's default) and `discard-aside` + (callers `operator` alone) gain `kept`, `form` and `fingerprint` and call those verbs; listing stays `backed-up` + (§302). Before any live data is set aside, the node agent stops the newer build of the module (§297). `now` and + `restore` say `ended` and `restored` on `mesh.seat.node-backup.event.ended...` and + `.restored...`, carrying the module, the kept data, its form, the fingerprint and `outcome` + (`done` or `failed`, with its `error`); the node agent's wait for either is bounded at 30 minutes, past which its + have says the wait, naming the seat, and the watchman's `delivery-waits` raises it. Test 36's whole case lives in + `mesh-host`, and starts the builds from before G by their fingerprints in the artifact store. Why: the design's + choice, one answer to three preparers (Q8, S9, Q-H6, C19; lead-47's ruling, 2026-11-11). How it is checked: test 36; + a call of `snapshot-kept` from another node's `node-backup` holder, and a `discard-aside` from any caller but the + operator, are refused by the bus; a failed restore says `restored` with `failed` and its error. - §406 **A catch-up names its tool and arguments.** A restore point records the catch-up tool and its arguments whole - (§299), and the restored module's catalog graph entry grants that tool to `holder:node-engine@same-node`. Why: the design's choice (Q-H7). - How it is checked: whole (node-engine), a restore runs its recorded catch-up. + (§299), and the fingerprint of the newer build it was taken before; the grants part derives the grant of that tool to + `holder:node-engine@same-node` from the catalog graph's entry of that recorded fingerprint (§443). Why: the design's + choice (Q-H7). How it is checked: whole (node-engine), a restore runs its recorded catch-up, granted from the + recorded build's entry. - §407 **The object store package.** mesh-sdk's object store package is `go/stateobjects`; it also takes a foundation part's old `objects` section (§58, §346). A reply or event over the limit is made an object by that package through §345's put session, and read back through the same session form for a get; the call that reads a sent object is @@ -132,9 +149,11 @@ line says so.* `kind:image`, `version`, the `*` emitter, an observer's finding stream, and an artifact's `needs`; `check` stays beside `pipeline` until the checker is removed (§97, §203). Why: readers first (ADR 0667 §4; S2, S18). How it is checked: unit (the release's reader), each form read. -- §410 **A foundation part's sent store keeps its send sequence.** mesh-sdk's sender keeps the sequence of a foundation - part's sends in the owner's old `state` section and ages `sent-objects` from it at each send (§330). Why: an - `objects` section has no sequence (S7). How it is checked: unit (sender), a send past 7 days ages the oldest. +- §410 **A foundation part's sent store keeps its send sequence.** mesh-sdk's sender keeps, per node, the sequence of + a foundation part's sends in the owner's old `state` section `sent-log`, one key `` written by compare-and-set + at each send, and ages `sent-objects` from it at each send (§330); `_state_objects` reads it. Why: an + `objects` section has no sequence (S7). How it is checked: unit (sender), a send past 7 days ages the oldest, and two + sends at once lose none by compare-and-set. ### Versions @@ -144,9 +163,11 @@ line says so.* module (§52, §374; Q15, S1, Q-H3, D14). How it is checked: unit (manifest validator), `series` refused. - §412 **The first fill's sources.** §372's fill reads, per module, the packages its catalog entry names in their ecosystems (the Go module path, the npm name); where the builder holds no version of a package, the forge's tags of - its repository (`go/vMAJOR.MINOR.PATCH`) are the floor. Why: the live builder answers none for mesh-sdk while the - forge holds `go/v0.1.14` (S17, C9). How it is checked: whole (indexer), a module with tags and no builder versions - fills from the tags. + its repository (`go/vMAJOR.MINOR.PATCH`) are the floor, only tags the forge protects. The fill is a kept call that + waits until both sources have answered for every module, and fills nothing until then, never part of the modules. + Why: the live builder answers none for mesh-sdk while the forge holds `go/v0.1.14` (S17, C9). How it is checked: + whole (indexer), a module with tags and no builder versions fills from the tags; with the forge down, nothing is + filled and `call-unanswered` is raised after five minutes; an unprotected tag is not read. - §413 **`tag-asks` and `version.numbered` go at G's delivery.** The builder's `tag-asks` and its event `version.numbered` are removed at G's delivery, as §373 has for the tagged versions; the build modules consume `version.numbered` no more from G. This amends §372. Why: the design's choice (D19). How it is checked: the @@ -166,12 +187,16 @@ line says so.* - §417 **Go's lint is gofmt and vet.** Go's lint step runs gofmt and go vet, in the lint step only (§328). Why: the design's choice (C8). How it is checked: whole (Go build module), a vet failure fails lint and no unit step. - §418 **The repository checks run as a step.** Each repository's own checks, which the checker runs today, run as a - pipeline step of its build seat from G's delivery. Why: the checker goes (C20). How it is checked: whole (runner), - a failing repository check fails its step. -- §419 **How tests are counted.** A test is a top-level Go test function or a TypeScript `test(` call; an existing - module ends G with no more tests than it starts with, and the new runner within 50 integration and 500 unit tests; a - module over the budget at its start is named in the pipeline's end. Why: the test budget per module (S16, D6). How - it is checked: `pipeline-ended`'s counts. + pipeline step of its build seat from G's delivery, keyed per repository and source revision, so a repository's + checks run once for a source revision however many of its modules it moves (ADR 0548); hq's check (its `go test + ./...` at its root) runs on the seat `node-build-go`. Why: the checker goes (C20). How it is checked: whole (runner), + a failing repository check fails its step, and a revision moving two modules of one repository runs it once. +- §419 **How tests are counted.** A test is a top-level Go test function or a TypeScript `test(` call, counted per + catalog module. A module ends G with no more tests than it starts with, and a module over its budget at its start + whose tests G's change touches ends with fewer (the test budget); the new runner stays within 50 integration and 500 + unit tests. `pipeline-ended` carries per module `tests` (`unit`, `integration`) and `over-budget` (yes or no); G's own + check, made by the running checker (§340), counts by the same rule. Why: the test budget per module (S16, D6). How it + is checked: `pipeline-ended`'s counts; unit (runner), a module over budget is named `over-budget`. - §420 **A run on request's key, and the step-run package.** A run on request is keyed by the run's id under its named branch (§54, §64, §85); the step-run code is the delivery SDK's package `sdk/steprun`, and the runner's client sits beside the other seats' clients; the runner's kept data layouts are the seat's `states` (§27, §306). Why: @@ -179,14 +204,19 @@ line says so.* ### Readers, branches and the node-engine -- §421 **The node-engine reads the catalog half for its branch.** The node-engine joins §196's readers: it reads the - catalog graph entries and verdicts of the modules it composes from the catalog half, never a manifest, of the branch each module's placement - names, and the parts by digest from its want (§379); its reads of the indexer's and builder's states go. The tool - runner follows every watched branch's newest `catalog-revision`, as §365. Why: ADR 0596 §2 (Q-H1, Q-H2, Q-T8). How it - is checked: the node-engine's manifest reads no other module's state; test 61. -- §422 **The node-engine's first-view tools are seat verbs.** The node-engine serves its view's two tools as seat verbs - of `node-engine`, beside its seat-list verbs, since it serves no module tools. Why: the design's choice (Q-H4). How - it is checked: the seat's fixtures. +- §421 **The node-engine reads the entry its want names.** The node-engine joins §196's readers: it reads, from the + catalog half, the catalog graph's entry of the fingerprint its want names (§443), never a manifest and never by + branch, so a want needs no field `branch`, and the parts by digest from its want (§379); its reads of the indexer's + and builder's states go. When the catalog half no longer holds that entry, the node-engine holds the want and its + have says the phase `entry-missing`, naming the fingerprint. The tool runner follows every watched branch's newest + `catalog-revision`, as §365. Why: ADR 0596 §2 (Q-H1, Q-H2, Q-T8; review of step 0b). How it is checked: the + node-engine's account holds no read of another module's state; test 61, extended to the node-engine; whole + (node-engine), a want naming an entry the half does not hold says `entry-missing`. +- §422 **The node-engine's first-view tools are seat verbs.** The node-engine serves its view's two tools as the seat + `node-engine`'s verbs `first-views` and `first-view-again`, beside its seat-list verbs, since it serves no module + tools: `first-views` a `read`, its callers any person and the healers, and `first-view-again` an `act`, its callers + the operator and the healers, as §204 names them. Why: the design's choice (Q-H4). How it is checked: the seat's + fixtures; whole (node-engine), a call from another caller is refused by the bus. - §423 **A kept-build wait says the existing words.** A have waiting for a kept build (§271) says the existing phase and words, with no new field. Why: the design's choice (Q-H10). How it is checked: whole (node-engine). - §424 **Each process's own build, and each bundle's.** A process says `own build unknown` in its @@ -217,15 +247,20 @@ line says so.* (gate), test 36's gate half. - §430 **The gate's sources before the first registrations.** The gate keeps `source.` per repository and watched branch, the branch escaped as §73, following the registrations, and writes `source.` for - every repository from its start, before the first registrations (§15, §95). Why: the design's choice (C12, D18). - How it is checked: whole (gate), `source` answers before any registration. + every repository from its start, before the first registrations (§15, §95). It starts from its own kept `source` + keys; the forge's heads it asks as a kept call (ADR 0668), so a gate started while the forge is down serves what it + kept, writes nothing for a repository it has no key of, and raises `call-unanswered` after five minutes. Why: the + design's choice (C12, D18). How it is checked: whole (gate), `source` answers before any registration, and with the + forge stopped it serves its kept keys and says `call-unanswered`. - §431 **The fate of the gate's other parts.** From G's delivery the gate's `asks` go with the Approve per merge; `deliveries`, `show`, `groups` and `stalled` are answered from the delivery records; `checks` and `settle` go with the - merge states, and the five verbs of release 6 leave the definition; the events `group` and `merged` go, their readers - moving to the seat `git`'s events, while `transition` stays; the reads of the teller's answers and the view's reach - are by their events, and of the checker's verdicts go with it. Readers of the gate's `source` move to the verb - `source` and `source-moved`, and the assigner reads no `merges`. Why: the design's choice (C13, C14, D9, D11). How it - is checked: whole (gate), each verb served or not as named. + merge states, and the five verbs of release 6 leave the definition; the events `group` and `merged` go, while + `transition` stays; their readers move: the knowledge base's delivery overview (what `knowledge-base.progress` + draws) reads the seat `git`'s `pull-merged` and the runner's `group-ended`, and the issue tracker and the tool runner + the same. The reads of the teller's answers and the view's reach are by their events, and of the checker's verdicts + go with it. Readers of the gate's `source` move to the verb `source` and `source-moved`, and the assigner reads no + `merges`. Why: the design's choice (C13, C14, D9, D11). How it is checked: whole (gate), each verb served or not as + named; whole (knowledge base), the overview shows a group's end from `group-ended`. - §432 **The edges a `needs` names.** An artifact's `needs` names artifact references `:` of the catalog graph's edges (§95, §121). Why: the design's choice (C21). How it is checked: unit (manifest validator). - §433 **The bus module reads the catalog half.** The bus module's `consumes` and its call of `indexer_bus_state` are @@ -239,42 +274,79 @@ line says so.* the design's choice (Q16, Q-H1's candidates). How it is checked: the seat's fixtures at G's heads keep it. - §436 **A presence event names the machine, not its publisher.** `machine-away` and `machine-back` carry the machine as a subject part named ``, which the grants part does not bind to the publisher's node, since the - watchman says them for another machine. This amends §389. Why: `` in a subject is the publishing node (§260; - S8). How it is checked: whole (watchman), the event for an away machine is published by the watchman's account. + watchman says them for another machine; publish on them is granted to the holder of `mesh-watchdogs` alone. This + amends §389. Why: `` in a subject is the publishing node (§260; S8). How it is checked: whole (watchman), the + event for an away machine is published by the watchman's account; the grants part's table test, a row refusing the + same event from any other account. - §437 **`finding-written` carries the finding's layout whole.** `finding-written` and each entry of `findings-stated` - carry the finding's layout as the state `findings` holds it whole (its `summary`, `source`, `observer`, `actions`, - `needs`, `resolver`, `ref` and `run` among it), plus `scope`, `id` and `since`, so a condition built from the event - alone loses nothing. This amends §383. Why: the design's choice (Q19). How it is checked: unit (writer), the event's - body holds every field of the key. + carry the fields §439 lists, so a condition built from the event alone loses nothing. This amends §383. Why: the + design's choice (Q19). How it is checked: unit (writer), the event's body holds every field of the key. - §438 **The record names every repository G builds.** Design 47's milestones row and frontmatter `code:` name mesh-tools and mesh-networking, and design 51's line on what a node-engine hears says it consumes the node-engine seat's `running` (§199). Why: the design's choice (Q-T1, Q-H11). How it is checked: the index test. ### Lead-47's rulings on the four stopped items, and the operator's rule on manifests (2026-11-11) -- §439 **The finding events' layout is a seat contract, and its writers are generated.** The bodies of - `finding-written`, `finding-cleared`, `findings-stated` and the finding's layout are defined in the seat - `mesh-conditions`' definition, beside `findings` and `findings-asked`; the seat generator (seatgen) generates the Go and - the TypeScript writers from it, so the forge module's TypeScript writer comes with it. mesh-sdk's `go/views` writer - takes the subject handed in by the seat's client and names no seat (§262). This amends §383 and §386. Why: lead-47's - ruling, 2026-11-11, on Q10, S6 and C15, one answer for the three. How it is checked: unit (seat generator), both - writers generated from the definition say the same bodies; whole (forge module), its writer says `finding-written`. +- §439 **The finding events' layout is a seat contract, and its writers are generated.** The seat `mesh-conditions`' + definition defines, in its section `bodies` (the bodies other modules say on their own streams, from which the grants + part makes no seat event or stream), the finding and the bodies of `finding-written`, `finding-cleared` and + `findings-stated`, beside `findings` and `findings-asked`. A finding's fields, the one list: `kind`, `scope`, `id`, + `at`, `since`, `severity`, `summary`, `headline`, `explanation`, `subject`, `evidence`, `source`, `observer`, + `owner`, `waiting-on`, `actions`, `needs`, `resolver`, `ref` and `run`; `finding-cleared` carries `kind`, `scope`, + `id`, `at` and `why`; `findings-stated` carries `at`, `asked`, `findings` and `pending`. The seat generator (seatgen) + generates the Go and the TypeScript writers from it, so the forge module's TypeScript writer comes with it. mesh-sdk's + `go/views` writer takes the subject handed in by the seat's client and names no seat (§262). This amends §383, §386 + and §434. Why: lead-47's ruling, 2026-11-11, on Q10, S6 and C15, one answer for the three; the list is the design's + choice. How it is checked: unit (seat generator), both writers generated from the definition say the same bodies; + unit (grants part), a body of `bodies` makes no stream; whole (forge module), its writer says `finding-written`. - §440 **`process-builds` is a node-engine seat verb.** The read of the build each process was started with is the - seat `node-engine`'s verb `process-builds`, of class `read`, its callers by §391's default, since the node-engine - serves seat verbs and no module tools (§422). This amends §262 and test 48. Why: lead-47's ruling, 2026-11-11, on - Q11 and Q-H5. How it is checked: test 48; unit (definition reader), the verb's default callers. + seat `node-engine`'s verb `process-builds`, a `read`, its callers any person, agent sessions and the healers, since + the node-engine serves seat verbs and no module tools (§422). This amends §262 and test 48. Why: lead-47's ruling, + 2026-11-11, on Q11 and Q-H5. How it is checked: test 48; the grants part's table test, its three callers. - §441 **The seat `mesh-grants` answers the grants a candidate composes.** The seat `mesh-grants` gains the read - `grants-for`: given a candidate change, the grants that the change's catalog graph composes, against the watched - branch's; its callers by §391's default. The running runner reads a change's grants for `widens` through it, and its - serving parts from the seat list by fingerprint (§71). This amends §401. Why: lead-47's ruling, 2026-11-11, on D15 - and Q12. How it is checked: whole (grants part, runner), a change widening a grant names it in `widens` from - `grants-for`. -- §442 **Only the indexer reads a manifest.** The indexer alone reads the manifests, to build the catalog graph; every - other part (the grants part, the condition keeper, the assigner, the runner, the tool runner, the node-engine, the - checks and the reviews) reads the catalog graph, the catalog half of the revision of the branch concerned (§196, - §421). This amends §50, §59, §89, §199, §249, §309, §386, §406 and §421, and the main file's node agent, its inputs - and the composition check. Why: the operator, 2026-11-11 about 03:05 CET at the terminal: "only the indexer uses the - manifest to build the module catalog". How it is checked: the catalog's validation finds no manifest read in any - module's code but the indexer's (code review), and the grants part's table test derives each grant from a catalog - graph fixture with no manifest. + `grants-for`. Its argument is the candidate: a source revision or a run's id, and its watched branch. The grants part + takes that candidate's catalog half by `mesh-catalog`'s `revision` (one of §195's readers of a candidate's view) and + answers, per module, the grants it would compose added and removed against the branch's newest, each named by its + subject and verb. Its callers are §391's default. The running runner reads a change's grants for `widens` through it, + as a kept call, and its serving parts from the seat list by fingerprint (§71); while the grants part does not answer, + `pipeline-ended`'s `widens` says `could not run`, naming `mesh-grants`, and holds nothing (§71: a widening is said, + never refused). This amends §401. Why: lead-47's ruling, 2026-11-11, on D15 and Q12. How it is checked: whole (grants + part, runner), a change widening a grant names it in `widens` from `grants-for`, and with the grants part stopped + `widens` says `could not run`. +- §442 **Only the indexer reads a manifest.** The indexer alone reads the manifests, to build the catalog graph, whose + entry carries the validated manifest whole (§443); every other part (the grants part, the condition keeper, the + assigner, the runner, the tool runner, the node-engine, the checks and the reviews) reads the catalog graph's entry + of the build concerned from the catalog half (§196, §421). Today's readers move: in mesh-catalog, `brother`, + `distribution`, the forge module's package registry and `mesh-build-go` read the entry they need by `mesh-catalog`'s + `entry` or `revision`; in `mesh-host`, the node-engine reads the entry its want names (§421). The one exception is + the bootstrap: `mesh-host`'s `mesh-bootstrap` and `mesh-compose` read the manifests from a checkout of the catalog repository, before + any indexer runs. This amends §50, §59, §89, §199, §249, §309, §386, §406 and §421, and the main file's node agent, + its inputs and the composition check. Why: the operator, 2026-11-11 about 03:05 CET at the terminal: "only the + indexer uses the manifest to build the module catalog". How it is checked: test 61, extended to the node-engine and + the grants part: whole cases whose accounts hold no read of a manifest; the grants part's table test derives each + grant from a catalog graph fixture with no manifest. +### From the review of step 0b (2026-11-11) + +- §443 **The catalog graph's entry carries the manifest, and is kept while a build names it.** Each catalog graph + entry carries the validated manifest whole beside the fields §174 names, kept as an object of the indexer's old + `objects` section by its digest (§179), so no size limit applies to it. The indexer keeps an entry while a kept + revision lists it, or a want (heard by `mesh-wants`' `wanted`) or a running build (heard by the node-engine seat's + `running..`) names its fingerprint, and removes it at the first revision after none does; the seat + `mesh-catalog` gains the read `entry`, which answers one entry by its fingerprint, so a build older than the newest + is read by the want's fingerprint. This amends §179 and §180. Why: §442; the design's choice. How it is checked: + whole (indexer), an entry no revision lists stays readable by `entry` while a want names its fingerprint, and goes + after the want moves on. +- §444 **The grants part derives each module's grants from the build placed.** The grants part derives each module's + grants from the catalog graph's entry of the build its want names (heard by `wanted`), never from a branch's newest + revision, so a change on a branch no placement names grants nothing. This amends §59 and §386. Why: §442; a grant + follows what runs. How it is checked: the grants part's table test, a widening on a branch no placement names + grants nothing, and the same widening once wanted is granted. +- §445 **The indexer keeps the manifests by digest for node-engines before G.** Until no node runs a node-engine from + before G, the indexer keeps writing each manifest by digest in its state `manifests`, which those node-engines + read; that state and its writing go in the first change after the node-engine seat's `running` events say every + node runs G's node-engine, the state through `drop` on a person's word (ADR 0595 §4). The node-engine's own manifest + in G uses no word the node-engine of the version before refuses, since that reader refuses unknown fields; the + manifest validator holds it to that reader's words at G's heads. Why: readers first (ADR 0667 §4). How it is + checked: unit (manifest validator), a row refusing a node-engine manifest with a word the older reader refuses; + whole (node-engine of the version before), it composes from a manifest by digest written by G's indexer.