Answer develop's fourth batch of questions on milestone G, and write the operator's words for the teller

Develop met questions the design did not answer on restore points, a bundle's
channel to the tool runner, the want's new fields, the finding stream's form
under ADR 0595 and ADR 0666, and per-branch views; each is now a design line
(G-12, §516 to §541) with its reason and check, so develop builds them and
decides nothing.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-11 12:38:56 +01:00
parent 529cba366b
commit 05b16d63bb
11 changed files with 401 additions and 36 deletions
@@ -267,7 +267,7 @@ check and deliver milestone G itself (ADR 0667 §2); each of them says so in a l
prerequisite step `bypass`) ends the pipeline refused within five minutes, naming the step and what it waits for,
never as a silent wait (research 086, R5); a step whose seat has no holder ends its pipeline failed, naming the seat
(ADR 0666 §17).
- §33 **A failed head is said to its author, then to the operator.** A `required` step that failed, or ended `could not
- §33 **A failed head is said to its author, then to the operator.** (§540) A `required` step that failed, or ended `could not
run`, on a watched branch's head is the runner's finding `pipeline-failed`, naming the module, the branch, the commit
and the step; the condition keeper raises it as the commit's author's for two hours and then the operator's, as ADR
0505 §5 and §6 have a delivery whose cure is its author's new head, and clears it when a newer revision of that branch
@@ -42,7 +42,7 @@ each the design's choice with its reason, §468 to §479 those of the runner's,
operator, 2026-11-11 at the terminal (develop question D-12): a refusal would be "hard-coded logic for no good
reason". How it is checked: unit (definition reader), a row where a verb G adds with no `class` takes `read`'s
callers; unit (seat generator), a definition with a verb naming no `class` is generated.
- §457 **The put session's wire form.** (§489, §490) §345's put session runs on the subject `<bundle call subject>.put.<call id>`.
- §457 **The put session's wire form.** (§489, §490, §518) §345's put session runs on the subject `<bundle call subject>.put.<call id>`.
Each chunk is one message whose body is the value's raw bytes, at most half the bus's maximum payload as the
connection reads it from the server, with the header `Mesh-Put-Seq` (a decimal from 1, one more each chunk) and, on
the last chunk alone, `Mesh-Put-Last: true`. The tool runner answers each chunk with `{seq}`, the sequence it took,
@@ -62,7 +62,7 @@ each the design's choice with its reason, §468 to §479 those of the runner's,
its own version". Why: the operator, 2026-11-11 at the terminal (develop question D-19); a build without a version
is §371's and §373's. How it is checked: whole (Go, TypeScript and image build modules), a built image's tag and
label, a Go program's `main.meshVersion` and a Node program's own version are the reserved version.
- §459 **`SeatsToPassOn`'s input.** mesh-sdk's `catalogue.SeatsToPassOn` takes the holdings on record, the
- §459 **`SeatsToPassOn`'s input.** (§536) mesh-sdk's `catalogue.SeatsToPassOn` takes the holdings on record, the
assignments (each a node, a module and its placement's watched branch), what the caller heard of each node and
module from the node-engine seat's `running` (a fingerprint, `stopped`, or nothing heard since its consumer began),
and a reader of entries the caller passes over its own view of the catalog half, which answers an entry by its
@@ -77,7 +77,7 @@ each the design's choice with its reason, §468 to §479 those of the runner's,
(ADR 0596 §2), and the function stays a pure rule (develop question D-14). How it is checked: unit
(`SeatsToPassOn`), a table with a row per case: a heard fingerprint, nothing heard (the branch's entry taken), a
`stopped` holder passing no seat, and an entry not answered keeping the holder on record and saying it.
- §460 **An asker says whether its key is still open.** mesh-sdk's kept-call form takes, beside the ask's key, a
- §460 **An asker says whether its key is still open.** (§531) mesh-sdk's kept-call form takes, beside the ask's key, a
function `open` the asker passes, which reads the asker's own state and answers whether that key is still open, and,
where one exists, the event that replaces the ask; it asks again only while `open` answers yes and no replacing
event was heard. An error of `open` is written in the asker's journal naming the key, and the form asks again: a
@@ -265,7 +265,7 @@ each the design's choice with its reason, §468 to §479 those of the runner's,
its own fact (ADR 0596 §2) (develop questions GIT12 and REG1). How it is checked: unit (`mesh-builds` contract),
`reserved` with `name` read; whole (builder, registry holder), a Go publish named by its module path is checked
against the module's reservation, and an unknown name refused.
- §479 **A branch's catalog view is named with its branch.** (§495) In mesh-sdk's `go/views` reader and process reader, a
- §479 **A branch's catalog view is named with its branch.** (§495, §521, §532) In mesh-sdk's `go/views` reader and process reader, a
first view of a per-branch state is named `<owner>.<state>.<branch>`, the branch escaped as a key's name is (§73),
so `mesh-catalog.catalog-revisions.<branch>` names one view per watched branch, a part reads several in one reader,
and `<module>_first_views` lists one row per branch (§358, §365). A view of a state that is not per branch keeps
@@ -128,13 +128,13 @@ reason. What a question of another kind leaves open waits for the operator and i
not answer the new calls (ADR 0595 §9; review round 1, security and upgrade 2). How it is checked: unit (tool
runner), each word stated with its family; whole (mesh-sdk), against a tool runner that does not state
`put-sessions` a large put fails naming it; the delivery plan of G orders the modules after the tool runner.
- §489 **Who publishes on a put or get session.** On `<bundle call subject>.put.<call id>` only the module's own
- §489 **Who publishes on a put or get session.** (§518) On `<bundle call subject>.put.<call id>` only the module's own
account publishes the chunks and only the tool runner of its node answers them; on `<bundle call subject>.get.<call
id>` only the tool runner publishes the chunks and only the module's account answers. The grants part grants them
so, as it grants a module's call subject today (ADR 0363 §2). Why: §457's subjects lie under a subject the module
already owns, so the grant follows the record (review round 1, security and upgrade 3). How it is checked: whole
(grants part, tool runner), a chunk published by another module's account is refused by the bus.
- §490 **The get side of a session.** A get of a value over the limit (§457) runs so: the bundle subscribes to
- §490 **The get side of a session.** (§518) A get of a value over the limit (§457) runs so: the bundle subscribes to
`<bundle call subject>.get.<call id>` before it makes the call; the tool runner's answer to the call is
`{chunked: <count>, size, digest}`, the value's `sha256:` digest; the tool runner then publishes each chunk as a
request on that subject, with `Mesh-Put-Seq` and, on the last, `Mesh-Put-Last: true`, and the bundle answers each
@@ -170,7 +170,7 @@ reason. What a question of another kind leaves open waits for the operator and i
release's publish (kind 1), so the runner's manifest is read by every part that takes it in. Why: readers first
(ADR 0667 §4; review round 1, security and upgrade's note). How it is checked: G's check reads the runner's and the
node-engine's manifests; whole (grants part), the runner's `pipelines` bucket has its cap.
- §495 **Small corrections from the review.** §472's "kind 3 is stale (§441)" reads §375. §472's `toolchain-agreed` carries its digests as they stood when the version was agreed; a digest that changes later at that version is read from `toolchain-reported` (§492) and starts nothing. A sent store already over its cap when §477's
- §495 **Small corrections from the review.** (§530) §472's "kind 3 is stale (§441)" reads §375. §472's `toolchain-agreed` carries its digests as they stood when the version was agreed; a digest that changes later at that version is read from `toolchain-reported` (§492) and starts nothing. A sent store already over its cap when §477's
cap is planned keeps no cap until its seven-day age brings it under, the bus module's plan naming it with its fill
meanwhile; a sent store is planned only for a module §344 names, and the plan refuses caps whose sum passes the
bus's storage limit, naming the sum. §468's "behind" is the age of the oldest message the consumer has not
@@ -197,7 +197,7 @@ reason. What a question of another kind leaves open waits for the operator and i
`branch-unprotected` stands (§17) raises none either. Why: the watchman already times each take-in wait (develop
question on §12). How it is checked: whole (watchman), a head behind a pending revision raises nothing for 60
minutes, then `take-in-waits`.
- §498 **A wait names its clock and its kind.** (§608) `meshwants.Wait`, the runner's wait body and the node-engine seat's
- §498 **A wait names its clock and its kind.** (§534, §608) `meshwants.Wait`, the runner's wait body and the node-engine seat's
gain `clock-from` (the time the bound counts from, §266, §269) beside `bound`, and `step`, one of the acting steps
of §203 or `put`, `delivery`, `kept-build`, `backup`; a put's wait (main file, *A put without hold that stands*)
is `step: put` with the node, the module and `fingerprint`; a dependent's delivery wait (§376) is `step: delivery`
@@ -205,7 +205,7 @@ reason. What a question of another kind leaves open waits for the operator and i
fingerprint, `held`, since and bound, from which the watchman seeds. Why: one wait form, told apart by `step`
(develop questions WM6 and WM10). How it is checked: unit (contracts), each field read; whole (watchman), a put's
wait raises `put-stands` and a pipeline's wait raises nothing for it.
- §499 **The node-engine says a kept build's wait, and its version is read from the catalog.** (§609) A node-engine of G
- §499 **The node-engine says a kept build's wait, and its version is read from the catalog.** (§541, §609) A node-engine of G
waiting for a kept build says `wait-held` on its seat with `step: kept-build`, `node` the build node, and why
(`node away` or `build no longer kept`), and `wait-ended` when it applies; its have's value carries the same as
`waits`. The watchman takes the keeping node from the builder's `build.ended` (§379), never its done key. Each
@@ -252,7 +252,7 @@ reason. What a question of another kind leaves open waits for the operator and i
never computed again from the manifest whole, whose encoding may differ; the module's value and §445's
`manifests` key are that digest. Why: the bytes, not the map, are what the node-engines before G read (develop
question IX16). How it is checked: unit (indexer), the entry's digest is the digest of the bytes read.
- §507 **The watched branches before the first registrations.** Every reader of a trunk's source revision reads, per
- §507 **The watched branches before the first registrations.** (§532) Every reader of a trunk's source revision reads, per
watched branch the registrations name, `source.<branch>` through the gate's verb `source`; before the first
registrations (§95, §353), the watched branches are the branches the gate's `source` answers, which G's switch
carries in from `source.main` as the branch `main`, read from the key and never fixed in code (§7). The assigner's
@@ -260,7 +260,7 @@ reason. What a question of another kind leaves open waits for the operator and i
and one source of the branches for every reader (develop questions Q18 and VW0, and the bridge's FB9). How it is
checked: whole (assigner, bridge), before the first registrations a want is written from `source.main`, and no
part's code holds `main`.
- §508 **The node-engine claims its seat as one module.** (§609) The seat `node-engine`'s definition in mesh-contracts no
- §508 **The node-engine claims its seat as one module.** (§527, §609) The seat `node-engine`'s definition in mesh-contracts no
longer marks it held by the engine; the manifest validator accepts one module of a revision claiming it and
refuses a second, naming both, in place of refusing every claim, and §494's release carries the rule. The
node-engine's guard reads the holder from the seat list (§364). Why: §364 has the node-engine's manifest claim the
@@ -301,7 +301,7 @@ reason. What a question of another kind leaves open waits for the operator and i
`membership.BusBinding`, built in mesh-sdk. Why: the objects template has no default (develop questions NATS1 and
on §399). How it is checked: unit (bus module's plan), each planned objects store has its cap; unit (membership),
both fields read.
- §514 **The teller tells through `notify`, on every channel.** For `widens` (§71, §335), `recovery-merged` (§81)
- §514 **The teller tells through `notify`, on every channel.** (§522) For `widens` (§71, §335), `recovery-merged` (§81)
and a `forge-made` record (§170) the teller calls the seat `operator-channel`'s verb `notify`, named in its
manifest's `invokes`, with `every-channel: true`, which the router sends on every channel's `send`, as design 46
announces a break-glass act. The words are the operator's to approve and wait for them (develop questions TL1 to
@@ -0,0 +1,364 @@
---
layer: to-be
status: in-progress
design: 47
milestone: G
updated: 2026-11-11
decisions:
- "ADR 0667"
- "ADR 0666"
- "ADR 0660"
- "ADR 0656"
- "ADR 0636"
- "ADR 0619"
- "ADR 0618"
- "ADR 0614"
- "ADR 0596"
- "ADR 0595"
- "ADR 0564"
- "ADR 0505"
- "ADR 0363"
- "ADR 0240"
- "ADR 0235"
---
# 47, milestone G: the operator's words of 2026-11-11 and develop's fourth batch of questions
One file of milestone G's part of [design 47](../47-delivery-from-commit-to-delivered.md); the part opens at
[G.md](G.md). Its design lines are numbered across every file of the part and cited as "design 47 G §n".
*§522 is the operator's answer of 2026-11-11 at 12:11 CET at lead-47's terminal. Every other line answers a question
develop met after [G-11](G-11-develop-answers-review.md), of internal form only (playbook 07, step 0b), each the
design's choice with its reason. What a question of another kind leaves open waits for the operator and is said in the
line. Questions that an earlier line already answers have no line here: develop reads that line.*
## Kept data on the bus: restore points and what is set aside
- §516 **A restore point's bytes, and the forms of `snapshot-kept` and `restore-kept`.** The seat `mesh-broker`'s two
verbs (§405) take and answer the forms its definition in mesh-contracts gives them, which this line makes the
design's: `snapshot-kept` takes `module`, `kept` (the kept data's local name), `form`, `fingerprint`, `why` and
`catch-up` as `{tool, arguments}` (§451), and answers `point` (the module, the kept data, its form, the
fingerprint, `snapshot`, `consumers` with each durable consumer's stream, name and acknowledged sequence, `size` in
bytes, `at` and `catch-up`) or `error` alone; `restore-kept` takes `module`, `kept`, `form`, `fingerprint`, `why`
and one of `snapshot` (the restore point's name), `aside-only` or `discard-aside` (an aside's `id`), and answers
`restored`, `aside` and `error`. No argument `local-name` or `from` is taken, and a catch-up is never text. The bus
module keeps a restore point in its own `snapshots` directory, which ADR 0235 §1 to §3 give it for the bus's dump:
the server's snapshot of each bus object of the kept data (its stream, or the stream under its bucket or object
store), taken one at a time with ADR 0235 §10's pacing and §11's bounds, and the point's record, in the directory
`kept/<module>/<kept>/<form>-<fingerprint>`, each token escaped as a key's name is (§73); that name is the point's
`snapshot`. The holder of `node-backup` backs that directory up as it backs up `snapshots` (ADR 0235 §3), so its
copy is the point's safeguard, never the point: when its `restore` finds the point's directory missing on the bus
module's node, it brings it back from its newest repository snapshot that holds it, under the same name, and only
then calls `restore-kept`; when none holds it, `restored` says `failed` with `restore point missing`, and §300 holds
the revert. `restore-kept` sets the live kept data aside by taking the server's snapshot of each of its bus objects
into `aside/<module>/<kept>/<at>` in the same directory (`at` the UTC time written `20261111T121200Z`), only then
removes the live objects, restores the point under their names and sets each consumer to its recorded sequence. The
aside's `id` is that directory's name, its `name` the bus name it was live under, its `size` its bytes on disk;
nothing of an aside stays on the bus, so it takes none of the bus's storage limit, and the definition's
description of `name` reads "the bus name it was live under". `discard-aside` removes that directory and nothing
else. No part removes a restore point in G: how long one is kept waits for the operator (issue 1921's note), and
until the answer is written here every point stays. This completes §405 and §406. Why: ADR 0235 has the bus
module's account write the bus's snapshots into its own directory and the backup holder back that directory up;
the server restores a stream only where no stream of that name exists, so the live data is set aside as a
snapshot before the point takes its name (develop questions BKP1, BKP3 and NATS4's argument names). How it is
checked: unit (mesh-broker's contract), each verb's input and answer read, an input naming `from` refused; whole
(bus module, backup holder), a point is taken, its directory removed, brought back from the repository and
restored, the live data's aside listed with its size and the consumer at its recorded sequence; a point missing
from both says `restore point missing`.
- §517 **`backed-up` reads the restore points and the data set aside from the backup holder's own state.** The holder of
`node-backup` on the bus module's node keeps what `snapshot-kept` and `restore-kept` answered it in its state
`bus-points`, asked in its `requires` by the template `state` (ADR 0595 §1; the holder is no foundation part, ADR
0619 §1, ADR 0666 §4): a point under `point.<module>.<kept>.<form>.<fingerprint>` with the answer's `point` whole,
written when `snapshot-kept` answers done; an aside under `aside.<module>.<kept>.<at>` with the answer's `aside`
whole, written when `restore-kept` answers one, each token escaped as a key's name is (§73). The holder deletes an
aside's key when `discard-aside` answers done, and deletes no other key in G (§516). `backed-up` lists both from
that state, each with its size (§302), and the holder's read tool of its state reads it. The seat `mesh-broker`
gains no read verb. The holder's old `state` entry `good` moves to `requires` in the same change, keeping its local
name and settings, as ADR 0595 §11 moves a module G touches. Why: the holder took each from its own call's answer,
so the list is its own fact (ADR 0596 §2), and a read verb on `mesh-broker` would answer what the caller already
holds (develop question BKP2). How it is checked: whole (backup holder), a restore's aside is listed by `backed-up`
with its size, is gone after `discard-aside`, and a restart of the holder lists the same.
- §523 **A seat event whose subject has parts.** A seat definition's `subject` with `<part>` tokens (§397), such as
`node-backup`'s `ended.<node>.<module>.<kept>` and `restored.<node>.<module>.<kept>` (§405), is said on
`mesh.seat.<seat>.event.` followed by the subject, each part filled in the definition's order: the seat
generator's subject function for the event takes each part as a string in that order and fills each as one token,
escaped as a key's name is (§73), refusing an empty part. A reader hears one module's events by the subject with
that module's tokens and `>` after them, and every module's by `*` for each part. Such an event has no key of its
own and is kept as its definition's `keep` says, or on EVENTS when it names no `keep` (§396). The holder's account
publishes it as a seat's holder publishes its seat's events today; no grant changes. Why: §397 fixes the subject's
words, not how a part is filled (develop question NATS4's wire). How it is checked: unit (seat generator), a subject
of three parts made in order and an empty part refused; whole (backup holder), `ended` heard by a reader of one
module's subject.
## The tool runner and its bundles
- §518 **A bundle's put and get sessions run on its channel to the tool runner.** A tools bundle reaches the tool runner
only over the channel the tool runner starts it with (its standard input and output) and holds no bus account, so
§345's put session and §490's get session run on that channel, as every `mesh/` call of a bundle does (ADR 0595
§9); `<bundle call subject>` in §457, §489 and §490 names that call, and no bus subject. A value at or under the
limit is put and got by one call, as today. Over it:
- **Put.** The bundle sends each chunk as the call `mesh/objects.put-chunk` with `name` (the object), `call` (the
bundle's id for this put), `seq` (from 1, one more each chunk), `last` (true on the last chunk alone) and `data`
(the chunk's bytes in base64, at most half the bus's maximum payload before encoding, §457). The tool runner
answers each with `{seq}` or `{error}`, the bundle sends the next only after a `{seq}`, and the answer to the last
is the put's answer; a `seq` that is not one more than the last taken is answered `{error}` naming both, and a put
not sealed within the call's bound is dropped (§345). The tool runner writes the whole as one object through the
object store's own chunking.
- **Get.** The tool runner answers the get call `{chunked: <count>, size, digest, call}` (§490), and the bundle asks
each chunk in order by the call `mesh/objects.get-chunk` with `call` and `seq`, answered `{seq, last, data}` or
`{error}`; the bundle checks the whole against `digest`, and a get not completed within the call's bound fails,
naming the object.
The headers `Mesh-Put-Seq` and `Mesh-Put-Last` of §457 are these fields `seq` and `last`. Nothing of a session is
on the bus, so §489's grants are not made and the grants part grants nothing for it. A module's process, which
holds a bus account of its own, writes and reads its objects on the bus through the object store package directly,
with the store's own chunking, and runs no session. The capability word `put-sessions` (§488) names these two
calls. This amends §345, §457, §489 and §490; in the get the bundle asks each chunk, since on that channel every
`mesh/` call is the bundle's. Why: the operator's answer to develop question D-13, chunks in order, each
acknowledged before the next, is kept whole on the one channel a bundle has (develop questions T-5 and T-7). How it
is checked: whole (mesh-sdk, tool runner), a value of a hundred times the limit is put and got back whole by a
bundle, its digest checked, and a chunk out of order fails the put naming both sequences; the grants part's table
test grants no session subject.
- §519 **A bundle's fingerprint is in the environment the node-engine composes.** The node-engine writes
`MESH_FINGERPRINT`, the fingerprint of the want it applies for the bundle's module, into each tools bundle's
composed environment, as it hands it to each process (§205); the tool runner starts each bundle with its composed
environment whole, and reads no catalog entry and no want for it. A bundle started with no value says `own build
unknown` (§424). This completes §424. Why: the want the node-engine applies is the one fact of which build a node
runs (§205; develop question T-12). How it is checked: whole (node-engine, tool runner), a bundle reads the
fingerprint of its module's want.
## The node-engine and the want
- §520 **`running` says a build's health, and the assigner reads health from it alone.** The node-engine seat's
`running.<node>.<module>` gains `healthy` (true or false), the health of the build that runs as the node-engine's
have holds it from the module's declared check (ADR 0240), and the node-engine says `running` again on the same
subject each time `healthy` changes, so the stream, kept last per subject, holds each build's newest health.
`stopped` (§365, §404) is said only when the have no longer holds the module, never for an unhealthy build. The
assigner reads a provider's health for rule 5, the canary's for rules 3 and 4, and a put's end from these events
alone, through its durable consumer that starts from the last message per subject (§199), and reads no have: a
provider of which nothing was heard since that consumer began counts as not healthy, so its consumers' new wants
are held as rule 5 holds any, and nothing falls back to the have. `SeatsToPassOn` reads no `healthy` (§459): an
unhealthy holder still holds its seat. The assigner's `reads` of the node-engine's have go. This amends §309 and
§404. Why: the assigner reads no other module's state (ADR 0596 §2), and a stopped build and an unhealthy one are
told apart (develop questions AS15 and AS16). How it is checked: unit (the node-engine seat's fixtures), `running`
with `healthy` read; whole (assigner, node-engine), a provider turning unhealthy holds a consumer's new want and its
recovery lets the want go, with the assigner's account holding no read of the have.
- §524 **The node-engine checks a want's parts by their digests.** A composition's archive, process and container
resources name a source and a digest, not an artifact, so the node-engine matches no resource to a `parts` key: it
applies a want only when the digest of every resource it fetched is among the values of the want's `parts`, and
every value of `parts` is the digest of a resource it fetched; otherwise it applies nothing of that module and its
have says the phase `parts-differ`, naming the digest. `parts` stays keyed by `<module>:<artifact>` for people and
the delivery record. This completes §379. Why: the digest is what is fetched and checked (develop question H-8). How
it is checked: unit (node-engine), a want whose parts and fetched digests agree applies, and one with a fetched
digest outside `parts` or a part not fetched applies nothing, naming it.
- §525 **A node-engine says it reads the want's new fields.** A node-engine of G states the capability `want-parts` in
its node record's capabilities (ADR 0614 §4, ADR 0618 §2), and the assigner writes `version`, `parts` and `kept-on`
(§526) into a node's want only while that node's record states it; that is §379's "once that node runs G's
node-engine". Why: ADR 0614 §4 has each node-engine state what it reads (develop question H-7). How it is checked:
unit (node-engine), the word stated; whole (assigner), a node whose record lacks it gets a want without the fields.
- §526 **A want names the node that keeps a kept build.** For a kept build (§271) the assigner writes `kept-on`, the
build node the builder's `build.ended` names as keeping it (§379), into the want beside `parts`; the node-engine
fetches that build through the seat verb `kept-artifact` of that node, and fetches a want with no `kept-on` from the
store. Nothing else names the keeping node, the builder's `builds` going (§421). This amends §271's "the builder's
done key names it so with its digest". Why: ADR 0596 §2 (develop question H-9). How it is checked: whole (assigner,
node-engine), a kept build's want names its node and is fetched from it.
- §527 **The node-engine's own module is read from the catalog half.** The seat list answers seat definitions alone
(ADR 0636), never who holds a seat. The node-engine's apply guard and its compose read their own module's name from
the catalog half of their view: the module whose entry claims the seat `node-engine`, which §508 makes one per
revision; the manifest validator, beside §508's refusal of a second claim, refuses a revision in which no module
claims it, naming the seat. §364's, §365's and §508's "from the seat list" read so, the condition keeper's too. With
no entry claiming the seat, which only a revision from before G can show, the node-engine applies nothing of that
revision and its have says `entry-missing`, naming the seat. Why: §364 and §508 have the node-engine claim its seat
as one module, so the claim names it (develop question H-15). How it is checked: unit (manifest validator), a
revision with no claim of `node-engine` refused; whole (node-engine), its guard protects the module its catalog
half names, and the code review finds no fixed name (§428).
## Findings and the condition keeper
- §529 **A part's finding state and stream are declared in its kept data's form.** A part's state `findings` and its
finding stream (§383) are declared as ADR 0666 §4 has a part declare its kept data:
- **A foundation part** (the manifest validator's list: ADR 0619 §1's parts as ADR 0666 §4 changes them, the runner
from G's delivery and the checker until its removal) declares `findings` in its old `state` section and the
stream `<module>-findings` in its old `streams` section, with the events `finding-written.*`, `finding-cleared.*`
and `findings-stated.*`, 7 days and 16 MiB, its oldest dropped (§383), published on
`mesh.stream.<module>.event.<event>.<node>` (ADR 0363 §2).
- **Every other part** asks both in its `requires`: the state `findings` by the template `state`, keeping its local
name and carrying its settings as options (ADR 0595 §11), and the stream by the template `events` under the local
name `finding-events`, with `max-age-days` 7 and `max-mib` 16, which the template drops oldest when full (ADR 0595
§3), published on its binding's subject, `mesh.bus.<module>.finding-events.<event>.<node>`. `mesh-healers`, whose
old `streams` declares `mesh-healers-findings` on main, moves it so in G's change.
The manifest validator applies ADR 0595 §11's count of old sections to no part of its foundation list (ADR 0619
§2), so the tool runner's and the checker's manifests are not refused for it, and accepts in a foundation part's
old `streams` the finding stream in the one form above, as it accepts a stream on its list of streams kept until
moved; every other old `streams` entry is judged as today. A part whose list entry is missing is a fault of the
list, fixed in the validator (ADR 0619 §3). The validator refuses a manifest whose state `findings` has no finding
stream in its part's form, or no `consumes` of `mesh-conditions.findings-asked` (§387). The writer (§461) is handed
the subjects from the part's binding or its old stream, as it is handed every subject. The catalog graph entry
carries the finding stream in either form (§365); the grants part makes the keeper's consumer of §386 on either
stream and grants each part publish on its own finding stream's subjects of its own node only, in either form; the
keeper takes the observer and the node from either subject. This amends §383, §386 and §387, whose "into the
manifest's `streams`" holds for a foundation part alone. Why: ADR 0666 §4 and ADR 0595 §11 put a part's kept data
in the templates unless it is a foundation part, and ADR 0619 §2 keeps the foundation's old sections whole; the
local name `finding-events` is the design's choice, since `findings` names the state and ADR 0595 §8 takes one
name per module (develop questions on §387, both validator refusals). How it is checked: unit (manifest validator),
a foundation part's old `findings` and finding stream accepted, a non-foundation part's old sections refused and its
template form accepted; the catalog's validation at G's heads refuses none of §387's manifests; whole (keeper, a
template observer and the tool runner), both forms' events raise a condition.
- §540 **The keeper hands a failed head to the operator after two hours.** The condition keeper raises
`pipeline-failed` (§33) with `owner` the commit's author, as the runner's finding names it, and two hours after the
finding's `since` sets the condition's `owner` to `operator-channel`, the seat the operator is asked through (a
seat's name, §451), and says that change as it says any change of a condition; the runner's finding keeps the
author. The keeper times the two hours on its own conditions from `since`, so after its restart it times them from
`since` again. Why: §33 has the keeper raise it as the author's, then the operator's (ADR 0505 §5, §6; develop
question COND7). How it is checked: whole (keeper), a `pipeline-failed` is the operator's two hours after its
`since`, and so after a restart of the keeper.
- §541 **The keeper hears what a node runs and the healers' attempts as events.** The keeper's `reads` of
`node-engine.have` and `mesh-healers.attempts` go (§434).
- **What a node runs.** The keeper consumes the node-engine seat's `composed`, `running` (with `healthy`, §520, and
`stopped`) and `wait-held` and `wait-ended` (§499), from the last message per subject (§199), and compares them
with the wants it hears from the assigner. The node-engine says `wait-held`, with `step: compose` and the reason,
for each hold its have writes (§300's `restore point missing`, §421's and §527's `entry-missing`, §524's
`parts-differ`, §499's kept build), and `wait-ended` when the hold ends.
- **The healers' attempts.** The seat `mesh-healers` says `attempt-changed` on
`mesh.seat.mesh-healers.event.attempt-changed.<condition>`, the condition's key escaped as a key's name is (§73),
carrying the attempt's value whole as its key in `attempts` holds it and `until`, the end of that key's
lifetime, or `removed: true` when the healer ends the attempt; the seat's definition, in its contracts module,
keeps it last per subject, 7 days and 16 MiB (§396). The keeper's durable consumer starts from the last message per
subject, and the keeper drops an attempt at its `until` on its own clock.
Why: the keeper reads no other module's state (ADR 0596 §2; develop question COND8). How it is checked: whole
(keeper, healers, node-engine), an attempt said is shown on its condition and dropped at its `until` or its
removal, a node-engine's hold is heard from `wait-held`, and the keeper's manifest declares no `reads`.
## Views of the catalog half, per watched branch
- §521 **An owner's view event names its state, and the key names the branch.** An event an owner says for a per-branch
state (`catalog-revision` for `catalog-revisions`) names the state as the owner's manifest names it,
`catalog-revisions`, and the key, `<branch>.<revision>` (§343); mesh-sdk's `go/views` reader and process reader
route it to the view `<owner>.<state>.<branch>` (§479) by the key's first token, the branch escaped as a key's name
is (§73), which the subject's last token repeats. No event names a state `<state>.<branch>`; mesh-sdk's code at
eed96854, which names it so, follows this line. Why: a state is named once, as its owner declares it, and the key
already carries the branch (develop question on §479 and §495). How it is checked: unit (`go/views`), one
subscription of a per-branch event routes two branches' events to their two views.
- §530 **`revision` says `none yet` in a field.** The seat `mesh-catalog`'s `revision` for a watched branch with no
revision yet answers `{none-yet: true}`, with no revision and no `error`; mesh-sdk's client reads `none-yet` as a
ready, empty view (§495) and never reads an error's text for it; `views.NoneYet` is the client's name for that
answer. Why: an answer is told by its fields, never its words (develop question on §495). How it is checked: unit
(mesh-catalog's contract), the answer read; unit (client), `none-yet` gives a ready, empty view.
- §532 **Every reader of the catalog half follows every watched branch, and adopts a branch registered while it runs.**
Every part that reads the catalog half per watched branch (among them the bus module, the status view, the
condition keeper, the tool runner, the assigner, the grants part and the runner) follows one view per watched
branch: the branches the registrations name, read by `registrations` at its start and followed by
`registration-changed`, and before the first registrations the branches the gate's `source` answers (§507); no part
names a branch in its code, the view's `main` included.
- **Adopted after the start.** mesh-sdk's views reader adopts a view after its start and drops one: on
`registration-changed` adding a watched branch the part adopts `<owner>.<state>.<branch>`, which takes its first
view at once and then follows; on one removing a branch the part drops the view and its row of
`<module>_first_views`.
- **One subscription per event.** The reader subscribes once per event, `<event>.>`
(`mesh.seat.mesh-catalog.event.catalog-revision.>`), and routes each event to its branch's view by §521, so two
branches never overwrite each other's handler; `meshcatalogclient` wires its views on that one reader, and the
runner's own wiring of `catalog-revision.>` goes for it.
- **The bus module across branches.** The bus module plans a module's kept data from the newest revision of each
watched branch that lists the module: each local name once, from the first of the module's watched branches, in
its registration's order, whose revision lists it; another branch asking that local name with other settings is
said as the bus module's `drifted`, naming the branch (ADR 0595 §6), and plans nothing.
This amends §358, §365, §421, §433 and §507. Why: no part fixes a branch (§7, ADR 0666 §5), and a registration may
add a watched branch while a part runs (develop questions NATS3, VW1 and COND6, and the client's lost per-branch
events). How it is checked: unit (`go/views`), a view adopted after the start takes its first view and follows,
and two branches' events reach their own views; whole (keeper, bus module), a branch registered while they run is
followed with no restart; the code review finds no branch's name in any part.
## The bus module's plans
- §533 **A module of the new form.** "A module of the new form" (§59, §344) is a module that is no foundation part.
The bus module tells it by its catalog graph entry declaring no old `objects` section `sent-objects`: a foundation
part whose entry claims a seat whose definition has a verb or an event, or declares an event of its own, declares
it (§59), and the manifest validator refuses such a foundation part's manifest without it, naming it. Why: the bus
module reads no list of foundation parts, which is the validator's alone (ADR 0619 §3; develop question on §59 and
§344). How it is checked: unit (manifest validator), a foundation part saying an event without `sent-objects`
refused; whole (bus module), a module of the new form gets a sent store and a foundation part none.
- §537 **A definition's included parts are resolved before they are counted.** The bus module counts a seat
definition's verbs and events after resolving the parts it includes: it reads each definition that includes parts
by the seat list's answer for that one seat, which resolves them (ADR 0636), and plans a sent store (§344) for the
seat's holders when the resolved definition has a verb or an event. Including parts alone counts for nothing.
Why: an included part may hold only shared bodies (develop question on §344). How it is checked: whole (bus module),
a seat whose verbs come only from an included part gives its holder a sent store, and one including only bodies
gives none.
- §538 **The bus module plans again when the bus-state entries change.** The bus module compares, for each module,
the bus-state entries the catalog graph entry carries with those it last planned for that module, kept in its own
state, and plans again only when they differ; it never compares the manifest's digest (§506), which changes with
any field. Why: what it plans is those entries alone (develop question on §433 with §506). How it is checked: whole
(bus module), a manifest changed outside `requires` plans nothing, and a changed option plans the difference.
## The runner, the checker and mesh-sdk's helpers
- §528 **The checker built from G's heads asks no group build.** From G's delivery the pipeline is the check and the
run on request the try (§66), so the checker built from G's heads makes no group check: its group build through
tagged versions (its check's group path, `judge.go`'s, and `tagwanted.go`) goes with `tag-wanted` (§373), nothing replaces it in
the checker, and a group's builds against its package members' digests are the runner's (§373, §465). Until G's
delivery the running checker makes G's own check with main's code (ADR 0667 §2). Why: §66 and §373 (develop
question CK10). How it is checked: the code review finds no group build in the checker of G's heads.
- §534 **The wait's `step` in the runner's body.** The runner's wait body keeps `step` as the pipeline step a wait inside
a pipeline is in (`lint`, `unit`, `integration`, `composition`, `review`, `approval`), and gains the value
`pipeline`, the acting step of §203, for a wait of the entries the runner holds for its new version (§266,
`runner_waits`); `clock-from` stands beside it (§498). The watchman tells them apart by the value: `pipeline` and
every value §498 lists are acting or delivery waits, timed by their bound (§269); a pipeline step's value is a
step's wait on a person, a build node or the revision view (§73), timed as §75 has it, a wait on a person owing no
progress (ADR 0666 §24). This completes §498 for the runner. Why: one field, told apart by its value (develop
question on §498). How it is checked: unit (runner's contract), both kinds read; whole (watchman), a runner's
`pipeline` wait raises `acting-part-late` past its 30 minutes and an `approval` wait raises no `pipeline-stands`.
- §535 **A missing build seat and a seat with no holder, each read where it shows.** The runner reads that no build
seat serves an artifact's language from the catalog half of its revision view: no entry whose `acts`, the acting
rules of the seats it claims, hold a rule `build` with `on` naming that language (§323); the pipeline then ends
failed at once, naming the language and the missing build seat. It reads that a seat has no holder from the step
itself: an ask on that seat's work queue whose `step-started` is not heard within five minutes ends the pipeline
failed, naming the seat (§32). It reads neither from the seat list, which answers definitions alone (§527), nor
from any holding. Why: §32 already ends a pipeline whose step nothing starts, and the catalog half is the runner's
one view (develop question Q-RN7). How it is checked: whole (runner), a fixture language with no build seat ends at
once, naming it; a seat whose holder is stopped ends within five minutes, naming the seat.
- §539 **The runner's tools are named `runner_`.** The runner's module, `mesh-delivery-pipeline`, names its tools with
the prefix `runner_`, so the design's `runner_catch_up`, `runner_waits`, `runner_release` and `runner_health`
stand, and its first-view tool is `runner_first_views`; `<module>_first_views` (§205) carries the prefix the
module's tools carry. Why: the design names the runner's tools so throughout (develop question RN1). How it is
checked: the runner's manifest, and `mesh_search` with "runner first views" finds `runner_first_views`.
- §531 **The kept-call form in Go.** §460's form is mesh-sdk's `busretry.DoKept`, which takes the ask's key, `open` (of
the type `busretry.Open`), an optional `replaced` and the function that writes the journal, and a process's call
through it is `process.Conn.CallKeptWhileOpen`, as mesh-sdk 19fb1dce has them. Why: a helper's API is the design's
(develop question R-5). How it is checked: §460's.
- §536 **`SeatsToPassOn`'s types.** §459's function in mesh-sdk's `catalogue` takes `holdings`, `assignments` (a list
of `Assignment` with `Node`, `Module` and `Branch`), `heard` (a function of a node and a module answering a `Heard`
with `Fingerprint` and `Stopped`, and whether anything was heard) and `entries` (an `EntryReader` with
`ByFingerprint` and `OnBranch`), as mesh-sdk e0f9356b has them. Why: a helper's API is the design's (develop
question R-4). How it is checked: §459's.
## The operator's words
- §522 **The words the teller says.** The teller says, through `notify` on every channel (§514), in the operator's
words:
- `widens`, one line per entry of the pipeline's end (§335): "Widening: `<module>` `<commit7>` on `<branch>` widens
`<kind>` `<name>`.", `<kind>` and `<name>` the entry's.
- `recovery-merged` (§81): "Recovery merged: `<module>` `<commit7>` on `<branch>`, named by `<caller>`: `<why>`."
- a `forge-made` record (§170): "Merged at the forge, not through the mesh: `<repository>` pull request #`<n>` at
`<commit7>` on `<branch>`; delivered like any merge."
`<commit7>` is the commit's first seven hexadecimal characters. This completes §514. Why: the operator, 2026-11-11
12:11 CET at lead-47's terminal, approved the words as the design writer proposed them. How it is checked: unit
(teller), each of the three said in these words with its fields filled; whole (teller, router), as §514.
## Questions an earlier line answers
These write nothing new; develop reads the line named.
- The tool runner's fallback of local commit 1015b38 for a foundation part's bundle goes: §407 binds that bundle to
its old `objects` section, and a binding that is missing fails loudly (ADR 0595 §1) (Q-T5, T-11).
- The re-read tool's callers of `seatlist.Part` are §204's for every part, the assigner's own list going (AS19).
- The bus module's cap of a state's objects store and the binding's `objects` and `sent-objects` are §513's (NATS1,
§399).
- The contracts' `Hold` is §194's view, the newest assignment half and the catalog half it names; the candidate's
whole-half reader is §195's and §441's, read by a run on request's steps, `grants-for` and the indexer's candidate
pass (contracts).
- The view's module value carries the entry's `manifest-digest` (§506) and computes none (VW1).
- `store-filling` is raised past 80 % and cleared below 70 % (§181).
@@ -47,7 +47,7 @@ One file of milestone G's part of [design 47](../47-delivery-from-commit-to-deli
Its size is the template's (ADR 0595 §3). An object store holds no space until a value is written to it, so the many
it adds reserve nothing; the few values over the limit (a delivery record, a catalog graph revision list, a test's
output) are estimated, as a guess, at under 1 GiB across the mesh.
- §59 **An object sent is readable by the modules it is for.** A reply's or an event's object is written to the sender's
- §59 **An object sent is readable by the modules it is for.** (§533) A reply's or an event's object is written to the sender's
**sent store**, `<module>_sent-objects`: the bus module plans it, with no manifest field, for every module of the new
form that serves a verb or emits an event, and a foundation part declares it as an old `objects` section
`sent-objects` (ADR 0619 §2). Its cap is the objects template's (ADR 0595 §3), 256 MiB (§477), and it keeps an object 7 days, after
@@ -97,7 +97,7 @@ names go, since every new acting part needed code changes elsewhere (research 08
what its new version is built from or needs (a base, a package, a provider) is acted on by its running version,
never waited for: the running build module builds the shared contracts and the registry holder, then the new build
module builds the rest, so ADR 0614 §6's cycle through them stays allowed, now for that reason.
- §271 **The artifact store's holder takes its own new build even when its seat is the one broken.** (§499) A build module
- §271 **The artifact store's holder takes its own new build even when its seat is the one broken.** (§499, §526) A build module
stores the artifacts it builds through the seat `oci-artifact-registry`, so the
holder of that seat is in its own build's path: its new build needs the store it replaces. As every holder's own
inputs are (above), that store is acted on by the running holder: the running holder stores its new build, and only
@@ -381,7 +381,7 @@ later change of a kept data's form, not as a case of this milestone.
ask the gate of milestone G raised after the restore point is not among the pending ones, so its answer is not read
and the operator is asked again. Whether the first look clears a merge kept in the restored `merges` that the forge
merged since was not read in the code; the catch-up test below proves it with the real builds.
- §300 **A missing restore point holds the revert, naming it.** When the restore point a revert needs does not exist, or
- §300 **A missing restore point holds the revert, naming it.** (§541) When the restore point a revert needs does not exist, or
`restored` does not come, the node agent applies nothing of that module, keeps what runs, and writes the have phase
`held` with the reason `restore point missing` and the module, kept data and form it names; the assigner asks the
operator (hold, or start the reverted build on the live data as it is), raises the condition naming them, and on
@@ -391,7 +391,7 @@ later change of a kept data's form, not as a case of this milestone.
(for milestone G, its delivery records and its graph revisions) is set aside and not read again; an Approve asked
and answered since is asked again, and one the gate asked before still reads its answer. The revert's Approve ask
says this in those words, naming each kept data restored.
- §302 **Its tools.** The seat `node-backup`'s `backed-up` lists each module's restore points of its bus data, with the
- §302 **Its tools.** (§517) The seat `node-backup`'s `backed-up` lists each module's restore points of its bus data, with the
kept data, the form and the fingerprint each was taken before, and the data set aside at each restore, with its
size; `restore` restores one; `discard-aside` removes data set aside by a restore, only on the operator's call, and
writes the act, who and why in the hand-act log of the seat `mesh-hand-acts`. `backed-up` and `restore` exist on
@@ -75,7 +75,7 @@ the seat `git` the verb `tag` (§349, §372, §375, §376, §370).
of the revision view, ADR 0656), and `entry` and `difference` on `mesh-wants` (ADR 0656), with the events of *What
each step says*.
§309 **The seat `node-engine`**'s event `running.<node>.<module>` carries, from research 085's milestone, the module, its
§309 **The seat `node-engine`**'s (§520) event `running.<node>.<module>` carries, from research 085's milestone, the module, its
fingerprint and the digest of its build's manifest, so the node-engine of another node and the grants part decide a
seat's pass from the catalog graph's entry of that build (ADR 0660 §2; *Who holds a seat is applied by one rule*). No verb is added.
@@ -43,7 +43,7 @@ record it follows from, and replaces the builder's own choice where one was made
### The runner and its steps
- §323 **A step's build seat is read from the artifact's language.** The catalog graph entry names each artifact's
- §323 **A step's build seat is read from the artifact's language.** (§535) The catalog graph entry names each artifact's
`language`, as its manifest's artifact entry says it and as the indexer's language map matches today; the runner
reads it from the catalog half of its revision view and asks lint and the test steps of the build seat whose
definition's acting rule `build` has `on` naming that language. With no such seat, or no holder of it, the pipeline
@@ -198,14 +198,14 @@ record it follows from, and replaces the builder's own choice where one was made
- §343 **Branch names the indexer's keys use.** `register` and `watch` refuse a watched branch named `candidate` or
`entry`, naming why, since the catalog keeps its revisions under `<branch>.<revision>` beside those two key forms.
How it is checked: whole (indexer), each is refused.
- §344 **The bus module plans a sent store from what the catalog already says.** It plans `<module>_sent-objects` for a
- §344 **The bus module plans a sent store from what the catalog already says.** (§533, §537) It plans `<module>_sent-objects` for a
module of the new form whose catalog graph entry claims a seat whose definition has a verb or an event, or declares
an event of its own, read from the catalog half of its revision view and the seat list; the indexer's event carries
no field `sends`. When a seat's definition gains its first verb or event later, the bus module plans the store for
its holders on the seat list's change. Why: no manifest field (*Any size*), and the catalog half is every part's view
(ADR 0656 §6). How it is checked: whole (bus module), a module claiming a seat with a verb gets a sent store, one with
neither gets none, and a definition gaining a verb gives its holder one.
- §345 **A large value reaches the tool runner in chunks.** A bundle's put of a value over the bus's per-message limit is
- §345 **A large value reaches the tool runner in chunks.** (§518) A bundle's put of a value over the bus's per-message limit is
sent to the tool runner as a put session on the bundle's call subject, named by the call's id, in chunks under that
limit, in order, each answered by the tool runner before the next is sent, and written as one object through the
object store's own chunking, its wire form §457's; a put not sealed within the call's bound is dropped by the tool runner and its call
@@ -279,7 +279,7 @@ record it follows from, and replaces the builder's own choice where one was made
candidates, and nothing is guessed. A contribution edge runs from a consumer's entry to the provider its requirement
resolves to, wherever that requirement carries values the consumer contributes. How it is checked: unit
(assignment graph), each step of the order and a hold.
- §358 **The catalog's shared view takes a branch.** The client's view of the catalog half is per watched branch, named by
- §358 **The catalog's shared view takes a branch.** (§532) The client's view of the catalog half is per watched branch, named by
its caller (§479). How it is checked: unit (client), two branches give two views.
- §359 **`difference` names its revisions.** `difference` with none of `from`, `to` and `group` is refused, naming the
missing argument. How it is checked: a unit row.
@@ -299,10 +299,10 @@ record it follows from, and replaces the builder's own choice where one was made
### The condition keeper and the node-engine
- §364 **The node-engine claims its seat.** (§508) The node-engine's manifest claims the node seat `node-engine` (ADR 0563), and
- §364 **The node-engine claims its seat.** (§508, §527) The node-engine's manifest claims the node seat `node-engine` (ADR 0563), and
the indexer and the node-engine's own guard read its holder from the seat list, keeping no module name. How it is
checked: the code review reads that neither fixes a module name (§7).
- §365 **The condition keeper finds its sources in the catalog.** The catalog graph entry carries the events each
- §365 **The condition keeper finds its sources in the catalog.** (§527, §532) The catalog graph entry carries the events each
manifest declares in its `streams`; the keeper takes a first view of the catalog half, and its sources are the
modules whose entry declares the finding events of §383, the node-engine among them, its holder read from the seat
list. It joins the readers of *Every other reader of which modules exist*, reading every watched branch's newest
@@ -486,7 +486,7 @@ record it follows from, and replaces the builder's own choice where one was made
dependency builds it (its build toolchain part). Every other kind (2, 4, 5 and 6) only orders. A change to a build
module's own code, which is no toolchain part, rebuilds nothing. Why: the operator, 2026-11-10 about 22:30 to 23:00 CET. How it is checked: unit (indexer's
graph), each kind's stale-or-order, and a build module's code change rebuilds no module.
- §379 **A want names the released version and each part's digest.** From G's delivery a want `want.<node>.<module>`
- §379 **A want names the released version and each part's digest.** (§524, §525, §526) From G's delivery a want `want.<node>.<module>`
names, beside its fingerprint and source revision, the module's released version, for people (none for a build of
another watched branch), and the digest of each of its parts; the node-engine fetches and checks each part by its
digest, never by the version. The assigner takes the digests from `version-released` for a released version, and from
@@ -32,7 +32,7 @@ each module's findings as events; a module states its findings from its own trut
tool-runner account stays as it is in G; no record is written for these answers, so each line that departs from a
record says so in its Why. Round 3 of the review by architectural domain (2026-11-11) completed these lines.*
- §383 **An observer says its findings as events on a stream of its own; the keeper reads no observer's state.** Every
- §383 **An observer says its findings as events on a stream of its own; the keeper reads no observer's state.** (§529) Every
module that writes findings is an observer (§387 names them) and says each change of a finding on its own stream
`<module>-findings` (ADR 0363 §1: under its name in capitals on the bus, its `events` `finding-written.*`,
`finding-cleared.*` and `findings-stated.*`, kept 7 days and 16 MiB, its oldest message dropped when full, since the
@@ -97,7 +97,7 @@ record says so in its Why. Round 3 of the review by architectural domain (2026-1
account publishes for; G changes neither that account nor its grants, a known limit. Why: the operator, 2026-11-11;
modules running as the machine's account are issue 1966's (note 193), whose fix carries its check. How it is checked:
none in G; the limit is named on issue 1966.
- §386 **A `*` emitter in `consumes` hears one event from every module that declares it.** A `consumes` entry
- §386 **A `*` emitter in `consumes` hears one event from every module that declares it.** (§529) A `consumes` entry
`*.<event>` takes the event `<event>` from every module whose manifest declares it, and is the one generic form for
hearing an event that many modules say; the keeper's `*.finding-written`, `*.finding-cleared` and
`*.findings-stated` are the first. The manifest validator takes `*` only as the whole emitter, and only before an
@@ -114,7 +114,7 @@ record says so in its Why. Round 3 of the review by architectural domain (2026-1
`*.finding-written` consumer one durable consumer on each declaring module's stream and none on a restricted
stream; whole (keeper, grants part), a fixture module that declares the events after the keeper started is heard,
and a keeper stopped while findings change catches up from its durable consumers at its start.
- §387 **G's change writes the finding stream into every observer's manifest.** In the same change G writes the stream
- §387 **G's change writes the finding stream into every observer's manifest.** (§529) In the same change G writes the stream
`<module>-findings` of §383 into the manifest's `streams`, and `mesh-conditions.findings-asked` into its `consumes`,
for every module that declares a state `findings` on main: `artifact-store-tools`, `claude-code`, `distribution`, `gitea`,
`mesh-build-go`, `mesh-config`, `mesh-healers`, `mesh-knowledge`, `mesh-provisioner`, `mesh-self-check`, `mesh-vault`, `mesh-watcher`,
@@ -108,7 +108,7 @@ line says so.*
(Q13). How it is checked: whole (indexer), `unwatch` of a placed branch refused.
- §403 **A held-back ask.** A held-back ask (§83, design 46 §6) is answered in `asks` with the state `held-back` and the
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
- §404 **The node-engine's events' bodies.** (§520) `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), and mesh-sdk's `SeatsToPassOn` counts such a module as not running on that
node, its input being §459's. Why: the design's choice (Q17). How it is checked: the seat's fixtures; unit (`SeatsToPassOn`), a row where a
@@ -116,7 +116,7 @@ line says so.*
### 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
- §405 **The bus module's restore points and node-backup's verbs.** (§516, §517) The seat `mesh-broker` gains `snapshot-kept` and
`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
@@ -132,7 +132,7 @@ line says so.*
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
- §406 **A catch-up names its tool and arguments.** (§516) A restore point records the catch-up tool and its arguments whole
(§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
@@ -208,7 +208,7 @@ line says so.*
### Readers, branches and the node-engine
- §421 **The node-engine reads the entry its want names.** The node-engine joins §196's readers: it reads, from the
- §421 **The node-engine reads the entry its want names.** (§526, §532) 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
@@ -223,7 +223,7 @@ line says so.*
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
- §424 **Each process's own build, and each bundle's.** (§519) A process says `own build unknown` in its
`<module>_first_views` (§205); each tools bundle's composed environment carries its module's fingerprint. Why: the
design's choice (S12, Q-T7). How it is checked: whole (tool runner), a bundle reads its fingerprint.
- §425 **A kept call asks again what its asker names.** An asker passes the kept-call form the ask's key and the event
@@ -268,9 +268,9 @@ line says so.*
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 `<module>:<artifact>` 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
- §433 **The bus module reads the catalog half.** (§532, §538) The bus module's `consumes` and its call of `indexer_bus_state` are
replaced by its view of the catalog half (§344). Why: ADR 0596 §2 (C22). How it is checked: its manifest.
- §434 **Findings name their owner and whom they wait on, and the keeper reads by events.** A finding of §33, §8 and
- §434 **Findings name their owner and whom they wait on, and the keeper reads by events.** (§541) A finding of §33, §8 and
§75 carries `owner` and `waiting-on`; the keeper's other reads are by events or verbs, and no homes rows are added.
Hand-written finding code in Go moves to the generated writer (§439). Why: the design's choice (C16, C17, C15's Go
half). How it is checked: the code review; the keeper's manifest reads nothing.
+2 -1
View File
@@ -76,7 +76,7 @@ file on 2026-11-10, and is cited as "design 47 G §n". A sentence that holds a d
stayed in the main file, and G builds what it says from G's delivery. A section named in italics is in this part, or,
when it is not here, in the main file.
The part is ten files, each read whole, its design lines numbered across them:
The part is thirteen files, each read whole, its design lines numbered across them:
- [G-1-pipelines-registration-and-steps](G-1-pipelines-registration-and-steps.md): pipelines per module: registration, watched branches, steps and policy, what holds a delivery, approval, groups, dependencies, a publish.
- [G-2-pipelines-sizes-checks-and-tools](G-2-pipelines-sizes-checks-and-tools.md): pipelines per module: any size, the pipeline makes the check, who may say what, health, recovery, tools, kept data, how G itself is delivered, the choices under ADR 0666 and ADR 0667.
@@ -89,4 +89,5 @@ The part is ten files, each read whole, its design lines numbered across them:
- [G-9-prepare-answers](G-9-prepare-answers.md): the answers to the questions of G's final prepare and develop's first questions (§391 to §455).
- [G-10-develop-answers](G-10-develop-answers.md): the answers to develop's second batch of questions, the operator's and those of internal form only (§456 to §479).
- [G-11-develop-answers-review](G-11-develop-answers-review.md): the operator's answers of 2026-11-11 noon, the review of §456 to §479, and develop's next questions (§480 to §515).
- [G-12-develop-answers-fourth](G-12-develop-answers-fourth.md): the operator's words of 2026-11-11 and develop's fourth batch of questions (§516 to §541).
- [G-13-review-round-3](G-13-review-round-3.md): the review of §480 to §515, rounds 2 and 3 (§600 on).