Merge pull request 'Design 47 G: the lead's answers A-112 to A-147' (#570) from design/47-G-lead-answers-8 into main

This commit was merged in pull request #570.
This commit is contained in:
2026-11-12 08:40:47 +00:00
@@ -448,3 +448,110 @@ names the principle that settles it, and is cited as "design 47 G A-n".
`ask-again`; `cancel` drops the asks' bounds and leaves what the build seats already took; the hand act's verb is
`mesh-pipeline-runner.<verb>`; a review ends every running pipeline at that commit and fingerprint waiting on one. A
review given after a pipeline ended passed is refused, as built.
- **A-112** (§633, A-71; principle 7, one way per kind of part) A process reads its settings as the builder does
(A-71): a file its manifest declares, its content `${config:<key>}`, read at its start; so the node-engine reads
`recovery-wait-minutes` from such a file, default 90 when it is missing. A bundle keeps `stdio.Config`.
- **A-113** (§297, §560, §541; principle 3, failure is loud and leaves nothing broken) A revert whose restore fails
after `Env.Stop` starts the newer build again and holds the move, saying why; a module is never left stopped. A form
change whose entries are not yet answered waits for them, never moves without its restore point. The hold says
`wait-held` (§541) as every wait does.
- **A-114** (§693, A-61; principle 7) The seat `mesh-wants`' `wanted` stream keeps the last message per subject with no
age limit (`max-age-days: 0`): it is each want's last word, read whole at a start.
- **A-115** (A-107, A-109, A-110; principle 7; corrects both) `serves` is a field of a process itself, beside its
`bus`, not inside it: the grants part adds the serve subjects to whichever account that process runs on, the
module's own when it declares no `bus`, so a process keeps hearing what it heard. Only a seat's verbs move to the
process: a module tool such as `builder_build` stays its tools bundle's (A-87).
- **A-116** (§636, §616; principle 7) A read of a seat holder's state names the seat, as §616 does for views:
`reads` takes `seat:<seat>.<state>` (route-proxy: `seat:mesh-provisioner.plans`); the grants part resolves it to the
holder on record as it resolves a seat's views, and the module finds the holder through mesh-sdk's seat-list reader
(the holder of the seat), naming no module in code; the tests that held code to a fixed name hold it to the seat form.
- **A-117** (§683, §614, §560, A-95; principle 7) At a start, until its assignments, haves and resolved values are read,
the node-engine's pass composes only the modules whose kept want and kept entry it holds, a kept want standing for
their placement, and leaves every other module as it runs; the full pass follows once the inputs are read. It writes
`entry-not-found` itself through its own writer (kind added, scope `module`, id the fingerprint, escaped). The seat
`mesh-recovery`'s `ended` and `restored` events gain `why` (the hand act's words for a cancel), regenerated, which the
recovery module fills and the node-engine's hold says.
- **A-118** (A-77, A-101, §167's checker that goes with G; principle 7) The shared `Asker` takes optional bound keys;
the builder arms them in its `bounds` state. The checker, which the runner replaces and which goes after G, keeps its
step bound as today and gains no `bounds` state.
- **A-119** (§7, §616, A-82, A-116; principles 1 and 7) The builder's floor takes its requirements from the catalog
half it already follows (each entry's dependencies), so `indexer_requirements` goes; it is woken by the catalog
revisions it already hears, so the forge stream's consume goes; the assignments view is named in the seat form of
§616 (`consumes` `seat:mesh-module-assigner.views.assignments`, `reads` `seat:mesh-module-assigner.assignments`, A-116),
its first view through the seat's verb `assignments`. No module is named.
- **A-120** (A-117, A-95; principles 2 and 7) The early pass takes the node's own record from the statement the
node-engine makes of itself (its tunnel key, sealing key and capabilities), held in memory and built before the
composer's watch starts, without the bus; no copy of the record is kept in the composition state.
- **A-121** (§554; principles 7 and 8) An old section's kept data is named as the bus composer of mesh-sdk names it
when it makes it: a state `KV_` and its bucket name (module and name joined by `_`), a log its log stream name
(`LOG_`, module, `_`, name), a stream its declared name as is, an objects section `OBJ_` and module and name joined
by `_`. The recovery module calls those mesh-sdk names; it writes no name of its own.
- **A-122** (A-116, §324; principle 7) The node-build-image seat's `build` act takes the bound the other build seats
take, `60m`.
- **A-123** (§682, §554; principle 2) `aside` takes its bus names from the catalog entry of the fingerprint the
node-engine's placement runs for the module: what is set aside is the data that runs.
- **A-124** (§682; principle 7) The seat's aside names every bus object of the kept data: `Aside.name` becomes the list
`names` in the mesh-recovery contract, regenerated; no names joined into one string.
- **A-125** (§655) The restore of one stream moves into mesh-sdk's bussnap beside its snapshot, and the bus module
imports it from there; the recovery module's builder moves it, in the same work.
- **A-126** (A-82, A-101; principle 7) Who holds a seat now is read by one mesh-sdk helper beside the seat list
(`seatlist`), through the assigner's `assignments` verb; operatorask and the view call it, and no part keeps its own
copy. The builder's holder at a catalog revision (`versions.HolderOf`) answers another question and stays.
- **A-127** (A-115 over A-109, A-110) `serves` is read only beside a process's `bus`: mesh-sdk's process parse, the
grants part's process-serve composition and the validator's test follow A-115; a `serves` inside `bus` is refused.
- **A-128** (A-116; principle 7) A `reads` in seat form `seat:<seat>.<state>` is parsed by mesh-sdk's state reader as
its own kind, kept apart from a module's read; the validator checks the seat declares the state, and the holder is
resolved where it is read, by A-126's helper.
- **A-129** (§657; principle 4) The seat's `kept-points` answer gains `unrestored`, the asides whose record ended at
`removed`, read from the engine; the tool `recovery_kept_points` shows it, and the health check reads the same.
- **A-130** (A-124, §557; principle 7) The events `set-aside` and `aside-discarded` carry `names` as `Aside` does; the
recovery module's two bounds are the settings `dump-wait-minutes` (default 60) and `point-keep-days`.
- **A-131** (corrects A-119's first view; §616; principle 7) The builder's first view of the assignments is asked of
the view's own first-view tool on its holder (`<holder>.assignments`), the holder found at runtime by A-126's helper
and the builder among the view's callers; the seat-form `consumes` of the view covers it, and the seat verb
`assignments` keeps its own answer.
- **A-132** (A-123, §556; principle 1) The recovery module learns the fingerprint a node runs for a module from the
node-engine seat's `running` event, kept last per subject and read as §556 (a `consumes` of its manifest); no call.
- **A-133** (§657, §567, §554; principles 3 and 7) The recovery module's manifest follows the validator: (a) its health
check is its tool beside the process check the other modules declare; (b) the `digests` state's cap is given in the
template's own form at 4 MiB, never as a second option beside it; (c) the template states `digests` and `findings`
are the module's own by its `requires` and are not listed again in the process's `bus`, which keeps its own account.
- **A-134** (A-16, A-26, A-28; principles 7 and 8) The licence manager's `binding.changed` carries the consumer as its
further part (`binding.changed.<consumer>`), the one form of G's seat events; mesh-vault and claude-code adopt it
through their views reader, and mesh-vault's two followers share its one writer.
- **A-135** (corrects A-133(b); ADR 0595 §3; principle 7) The state template takes no cap: `digests` declares none and
the template's fixed cap stands; §567's 4 MiB is the size expected, not a setting.
- **A-136** (§483, §496; principle 1) The watchman's read of the build seats' steps goes, as §483 says: it times a
running ask from the build seat's step-progress event; its `reads seat:node-build-*.steps` and the holder lookup
for it go with it, and no holder event is needed.
- **A-137** (§681, A-123; principle 2) Before a keeper's snapshot is restored, the recovery module sets aside the bus
names of the restore's module and kept data from the catalog entry of the fingerprint the node is running; for an
unprotected snapshot, the `stream` snapshot-get answers.
- **A-138** (§557, §551, A-77, A-130; principles 1 and 7) The wait on snapshot-restored and the expiry are bounds as
well: settings `snapshot-restore-wait-minutes` (default 90) and `expire-every-hours` (default 24); every bound of
the module may be a fraction, so a whole test sets seconds; the expiry runs on a bound key's expiry, not a timer.
- **A-139** (§681; principle 7; code shared between modules is in mesh-sdk) The chunks of a seat verb's answer are
received with mesh-sdk's own form (`buscalls`), the one the bus module sends with; where mesh-sdk has no receive,
it is added there, never built in the recovery module.
- **A-140** (§681; principles 3 and 7) After its cancel is asked at the bound, the recovery module waits one more bound
of `snapshot-restore-wait-minutes` for that act's snapshot-restored; none heard is "answers neither". A keeper that
answers `busy` ends the act failed before any aside, naming the keeper's running act.
- **A-141** (§562; principles 1 and 7) The recovery module learns of a move from its own stop: from the stop signal
on it answers every new call with an error naming the stop, cancels the running act so its own failure path runs,
and ends every accepted act not ended `stopped` with its ending event; a restart is the same.
- **A-142** (§496, §602; principles 1 and 7) A `step-ended` said while the watchman was down reaches it on its
start through its durable consumer of EVENTS, and ends the stuck ask then; nothing re-reads the steps and no
expiry is added.
- **A-143** (A-77, A-138; principle 1) The recovery module's dump wait and snapshot-restored wait are bound keys in
its state `bounds` as well, their expiry heard on its watch; no timer stays in the process.
- **A-144** (ADR 0625 §4 over §614 and §670's placing; principle 7) A client imports only its own seat's contract,
mesh-sdk and its domain SDK: the key codec `meshcatalogkey` moves into mesh-delivery's domain SDK, imported there
by the builder and the catalog client, and the source-branches follower's use of the `mesh-delivery` seat's types
moves into the domain SDK too; the catalog client keeps the mesh-catalog contract and the domain SDK only.
- **A-145** (§621, §494, §697, ADR 0633 §6; principle 7) The second reader release carries only §621's words and what
the trunk validator needs to judge the new indexer's manifest and the `by-caller` definitions; §529's finding-stream
rules and A-116/A-128's seat reads are G's own validator rules, judged by the change's validator, and stay in G.
- **A-146** (A-145, §529, A-30; principle 5) The second reader release also carries §529/A-30's exception for a
foundation part's kept old sections, and only that, since the trunk validator must accept the new indexer manifest.
- **A-147** (A-123, A-132, A-137; principle 3) While a module runs at two fingerprints (a move under way), a recovery
act on its kept data is refused, naming both; the caller asks again once the move has ended.