Merge pull request 'Design 47 G: the lead's answers A-148 to A-273' (#572) from design/47-G-lead-answers-9 into main

This commit was merged in pull request #572.
This commit is contained in:
2026-11-12 09:28:54 +00:00
3 changed files with 489 additions and 0 deletions
@@ -555,3 +555,136 @@ names the principle that settles it, and is cited as "design 47 G A-n".
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.
- **A-148** (A-145; principle 7, one release one check) A trunk fault that fails a release's own check rides that
release as its own commit, as fix 1975's distribution test did: the second reader release carries the builder's
by-hand answer fix (an ask is answered as put only after its put; issue 1126, ADR 0668 §1).
- **A-149** (§634, §527, A-120; principles 2 and 7) The node-engine knows its own name at start from its applied
store: the record of the module whose fingerprint is its own `MESH_FINGERPRINT`; the finding writer, discovery and
the vault login use it. Only on a first start with no such record do they wait for the first composing to name it.
- **A-150** (§563, A-107, A-115; principles 1 and 7) restic's `night` process, which dumps, gets a `bus` of its own
(its own broker account, as the recovery module's process has) and says item-started and item-ended and reads the
recovery module's events itself; no local request to the tools runtime, and the backup does not move into it.
- **A-151** (§465, ADR 0614 §2; principle 7) The three build modules `require` the provision `artifact-store` to read a
group member's build, with a `binds` file as go-package-registry's (`at`, `serves.port`), and read the blob by the
store's own path `<at>:<port>/v2/<module>/<artifact>/blobs/<digest>`; they never write into it, so ADR 0614 §2
holds, and their manifest tests assert the read.
- **A-152** (§472, §492; principles 3 and 7) The toolchain's `digest` is the sha256 of the toolchain program the build
module runs (the `go` or `node` it finds), computed at its start and again when the toolchain's version changes; no
field is added to the provision.
- **A-153** (§559, E §1; principles 7 and 8) The tool runner resolves a `deliver: new` subscription's key
`<emitter>.<event>` to its subjects with mesh-sdk's `buscompose.EventSubjects`, the one rule from an event name to
its subjects (a seat's event subject or the module's); a pattern with a wildcard is refused with `{error}`.
- **A-154** (design 46 approval mark §4, §16, §19; principles 7 and 8) The approval mark's three findings take scope
`machine` and the id `<node>.<module>`, `<node>.<ask id>` or `<node>.approvals`, escaped as a key's name, with the
subject of the tool runner on that machine, as the runner's first-view findings already do.
- **A-155** (§561, §563, §302, A-77; principles 1, 2 and 3) restic's put-off wait for a restore is a bound key in a
state of its own on the bus, bounded by the setting `put-off-bound`: the key is the put-off record `backed-up` reads,
its expiry raises `backup-waits` and ends the wait, so the night never holds its lock without a bound and no file
or timer keeps it. BKP7 is not built: §555 gives `restore` its class's default with no own-item limit.
- **A-156** (§610, A-82, design 51 *The move*; principle 7) Once distribution's `callers` list goes, the windows'
driver takes "every build module" as the modules that claim a build seat (`node-build-*`) in the catalog half it
follows, the one source A-82 gives; the holder's own per-verb `Allowed` checks go with the list, since §610's class
defaults are applied where the call is read, and the refusal of an unproven caller is that reader's.
- **A-157** (design 46 approval mark §16, §19, ADR 0668 §1, A-77; principles 1 and 3) Each try of `warranted` is a
`DoKept`; past its bound the call is made again when the hand-act seat's holder is heard again (the seat-holders
view the runner follows) and at each start; `call-unanswered` is raised on the expiry of a five-minute bound key per
ask, not a timer. A failed read or write of `approvals` is made again at the next marked call and at the next
membership change the runner hears.
- **A-158** (design 46 approval mark §16, §677; principle 8) A marked call's answer is `{answer, approval}`: the tool's
own answer and the line naming the approval, the form a process holder's `gated-ended` has, so a caller reads one
form from both gates. A-157's bound key lives in the runner's state `bound` as `<node>.unanswered.<ask id>`.
- **A-159** (§466, §472; principles 3 and 7) A build's `resolved{package, version, digest}` names what was used: its
`version` is the commit the ask names, and its `digest` the sha256 of what was laid (the Go module cache zip, the
npm tarball), or the member build's digest when it was laid from `builds`.
- **A-160** (§64, §190, §321, A-85, A-93; principle 7) A run's candidate is keyed by its run id `run-<id>` from the
runner's `run-started`, beside `try-<n>`; each member {module, commit, branch} maps to its repository by the
registrations and to the branch's revision view as its trunk; its manifests and fingerprints come from the same
branch take-in the indexer computes for any commit (its files read through the seat `git`), so no checker preview
is heard.
- **A-161** (§522, §81, §170; principle 1) An event carries what its hearers need to say it: `recovery-merged` gains
`module` and `branch`, and a forge-made record's `record-opened` gains `repository`, `pull`, `commit` and `branch`,
in their contracts and from their emitters; the teller makes no call per message.
- **A-162** (amends A-100; §575, A-94, ADR 0596; principle 1) The builder's `build.ended` is said for every end of a
build, carrying `outcome` (done or failed) and, when failed, `error`; the assigner's hold says "failed: <error>"
from it and "is being built" while no `build.ended` of that fingerprint is heard. The assigner never reads the
builder's `builds` bucket; its read there (put.go:85, the manifest's `reads`) goes.
- **A-163** (§543, §544; principles 7 and 8) The asker in an ask's accept subject is the asking seat's own name
(`mesh-pipeline-runner`, `mesh-catalog`, `mesh-wants`, `mesh-builds`, `mesh-delivery-checker`), not a nickname, so
steprun checks it against the callers the build seat's definition lists, read from the seat list; no table of its
own and no name map. A body's kind is the word the seat definition gives; a queue keeps its own name.
- **A-164** (§468, §76, §495, A-115; principles 4 and 7) The runner's process writes each durable consumer's oldest
unacknowledged age into a state of the runner's own when it changes; the bundle's `runner_health` reads that state,
its own module's, and asks no seat verb of itself; tools stay the bundle's (A-115).
- **A-165** (§610, A-156; principles 3 and 7) The class defaults of §610 are applied where a seat's verb is answered:
mesh-sdk's seat server (`conn.AnswerSeat`) and the tool runner's `serveSeats` read `seatdef.EffectiveCallers` and
refuse a caller outside them, the unproven one included, before the holder runs; a holder keeps no caller check of
its own.
- **A-166** (A-164, §76, §495; principles 1 and 7) The runner keeps a state `consumers` (history 1, a key per
consumer) holding the time its oldest unacknowledged message was delivered, written when a message is delivered or
acknowledged; `runner_health` works the age out as now minus that time when it is read, so nothing is read on a
timer.
- **A-167** (§354, §63, §22, §64, §357, §298; principles 1, 2, 3 and 7) For the assigner's composition step (AS5): its
`run` builds the node-engine's composer (`mesh-compose`) at the fingerprint the node-engine runs; each machine's
input is asked of that node's engine by `compose-candidate`; the machines are the nodes the branch's revision places
the module on; a node is asleep when the watchman's `machine-away` is heard for it; `mesh-compose` reading
`MESH_RUN_INPUT` and answering the run's output is the node-engine's, a row of its own. An entry held for want of a
provider (AS14) carries a field `held` naming the candidates, never only a log line. A revert (AS17) is a want that
goes back to an earlier fingerprint, which the assigner computes itself; a kept data's `form` is read from the
catalog entry's kept declarations (`catalogue.KeptDeclarations`). AS14's named seat and contribution edge, and
AS17's ask of the operator, go to a design line.
- **A-168** (E §33, design 46 approval mark §5; principle 3) For a marked wait on a module the runner does not serve,
the marks are the union of the newest entry of every followed branch; where the runner serves the module, its
served entry is added to that union. A mark is never lost.
- **A-169** (§579; principles 2 and 7) A pins state keys a revision by the revision object's own name (the assigner's
`trunk.<n>`, the indexer's `<branch>.<revision>`), value `{records, missing?}`, and holds two more keys in the same
form in every holder of pins: `made`, written once by create-only when the state is first used, and
`pins-stated`, the `at` of the applied event; pins count only once a `pins-stated` later than `made` is applied.
- **A-170** (§600, §481, §415, A-163; principles 7 and 8) Every ask to a build seat rides `accept.<queue>.<asker>`;
its kind is in its body only, as §600 says. A build seat definition's `stream` names only the queue, and the
generated accept subjects follow; the kind in the subject goes. §543's main subject takes `build` and `run` as
written, the checker's asks riding it until it goes.
- **A-171** (§579, A-169; principles 2 and 8) The `pinned` event's `catalog` entries name their branch: each is
`{branch, revision}`, in the mesh-delivery seat's definition and from the gate that says it, so a holder keys the
pin `<branch>.<revision>` from what the event says.
- **A-172** (§653, §431, A-161; principles 1 and 7) With the Approve per merge gone, the teller's merge-ask path goes
whole (its reads of the gate's `asks`, its handlers and their tests); the teller keeps `answers` and `answered` for
the assigner's asks only. A view's answer reaches it by the view's event, as §431 says, never by reading the
view's state. The gate fills `recovery-merged`'s `branch` from the branch it merged into and its `module` from the
catalog half's registrations; while no path of the gate opens a forge-made record, the teller says none.
- **A-173** (§507, §512, §532, A-103; principle 7) The view derives each watched branch's source on its own: the
source row and `delivered` per branch, a repository's reach from the source of the first branch of its
registration (before the first registrations, the branches `source` answers), and `view_tiers` with no revision
answering per branch; no branch is named in its code.
- **A-174** (§64, §190, A-160, A-93; principles 2 and 7) The indexer keeps a state `runs` (key `run-<id>`, value the
members and the modules whose pipeline ended), written on `run-started` and on each of the run's `pipeline-ended`,
removed with the candidate, so a restart loses nothing. A member on a branch its registration does not watch takes
the trunk's revision view as the base of its take-in; one on a watched branch takes that branch's.
- **A-175** (§512, §431, A-43, A-172; principles 1 and 7) The teller says its `answers` as a plain views family
`views.answers`, and the view says its own `answers` the same way; each follows the other's by mesh-sdk's
`ProcessReader.Follow` (first view through the owner's tool, then its views family). That is the "event" A-172 and
§431 mean; no own follower and no module-event adopt are added.
- **A-176** (A-166, §579, §76; principle 7; code shared between modules is in mesh-sdk) A process writes its durable
consumers' facts (stream, name, acknowledged sequence, pending, last event applied and its `at`, and when its oldest
unacknowledged message was delivered) into its module's own state `consumers` (history 1, a key per consumer) through
one mesh-sdk helper, after each message it applies; the runner and the indexer use it, and their tools read that
state.
- **A-177** (design 46 approval mark §4; principle 7) mesh-sdk's compiled `catalogue.Verb` gains `NeedsApproval`,
copied by `SeatsFromDefinitions` from the definition, so the validator and every reader of the seat list read a
verb's mark from one place.
- **A-178** (A-175, A-43; principles 7 and 8) The view says its `answers` as other owners say theirs: a read tool
`view_read_answers` (mesh-sdk `views.ReadTool`, in the view's tools bundle, the teller among its callers) and a
marks state `view-marks` (history 1), as the assigner and the indexer have; the teller's side is the same, with
`teller_read_answers` and `teller-marks`.
- **A-179** (refines A-165; §610, §336; principles 3 and 7) Where a seat's verb is answered, an unproven caller is
refused, and so is every caller when the verb's effective callers are empty; a proven caller is taken as among
them, since the grants part composes a verb's call subject only for the callers its effective list names, so the
bus holds the rest out. `seatdef.DefaultCallers` follows §610 (act, warrant and accept: operator, sessions and
invokers).
- **A-180** (§64, §420, A-160, A-174; principles 1 and 7) The runner places a run's pipelines when it hears the
catalog seat's `catalog-revision` for the candidate `run-<id>` (a candidate's revision, its subject naming it),
reading the candidate's entries and fingerprints through the seat's `revision` verb with the candidate's group;
`<id>` is a random 12-hex id the runner makes, so two runs of one commit are two pipelines.
- **A-181** (amends A-100 and A-162; §556; principles 1 and 2) The builder's `build.ended` stream keeps the last
message per subject (one per fingerprint), and the assigner reads it whole at its start as §556 reads a kept
stream, then hears it; so what was built, and a failed build's error, survive its restart and it reads no builder
bucket. `assigner_put`'s fingerprint-prefix form goes: a put names the whole fingerprint.
@@ -0,0 +1,355 @@
---
layer: to-be
status: in-progress
design: 47
milestone: G
updated: 2026-11-12
decisions:
- "ADR 0667"
---
# 47, milestone G — the lead's answers to develop's questions, continued
The answers of [G-20](G-20-lead-answers.md) go on here, since that part reached its size bound: each one line, naming
the principle that settles it, cited as "design 47 G A-n".
- **A-182** (§31, §350, §119; principles 2 and 7) A superseded step's ask is dropped where it stands: a taken step
keeps the node `ask-taken` named, and the drop is asked of that node's holder of the build seat; an untaken ask's drop
is asked of any holder, which records it in the seat's shared drop key, so no holder takes it. Steps on `mesh-builds`
and `mesh-wants`, whose seats serve no `drop`, are only ended superseded.
- **A-183** (design 46 approval mark §4, §23; principles 3 and 7) A manifest that marks a verb nothing enforces is
refused by the validator wherever it runs, as every rule's problem is; the indexer's "set aside to wait" is only its
reading of a field it does not yet know (the reader edge of §23), so no new waiting verdict is added.
- **A-184** (clarifies A-170; §543; principle 3) Until main's subject goes, it also takes the checker's `check` and
`recheck` asks, so no ask that runs today is refused by G; a queue is only `delivery`, `check` or `recheck`, and
steprun's `AskKinds` lists no `step` queue.
- **A-185** (A-180; principle 7) The catalog client (`meshcatalogclient`'s catalog follower), which already hears every
`catalog-revision`, hands a candidate's revision it does not keep to a hook its caller sets; the runner sets it to
place a run's pipelines. mesh-sdk's event hub keeps its one handler per pattern.
- **A-186** (A-179; principles 3 and 7) `conn.AnswerSeat` takes the seat's definition from its caller, which reads it
from the seat list it already follows; a verb the definition does not hold, or a definition not yet read, is
refused for every caller and said so, so a holder answers only once its seat list is read.
- **A-187** (A-176, §76; principle 3) The consumer ledger keeps a message's first delivery time: a message delivered
again (asked again, or after a restart) keeps the time it was first delivered, so a message that never settles
grows old and §76's check fires for it.
- **A-188** (A-172, §170, §151; principles 3 and 7) A take-in writes its entries (each with its module) into the
gate's record, so `recovery-merged`'s `module` is filled from the record; no forge-made open path is built, since
G ends the mark (§151). A record of the old milestone form, made before G, says no branch.
- **A-189** (§376, §374, A-181; principles 1, 2 and 7) At its start the assigner reads whole, as A-181 reads
`build.ended`, the streams of its own `version-delivered` and of the catalog seat's `version-released`, so it says
each version delivered once and knows the released ones. A dependent whose want changes fingerprint waits, by an
edge of kind 2, 4 or 6, for its dependency's newest released version on the dependent's branch not yet said
delivered; on a branch where no version is released there is no wait.
- **A-190** (ADR 0668 §1, §2; principles 3 and 7) A kept call is kept only while what it serves still stands; for the
indexer's four: `messageVia` while the commit's take-in is still pending, `stepsVia` while the candidate is held,
`sourceVia` while the branch is watched, `versionsVia` while the module is in that branch's newest view. Once
that ends, the call stops and is not said unanswered. `pin-missing` takes scope `module`, id
`mesh-delivery-indexer.pin.<key>`.
- **A-191** (§33, §540; principle 3) A `pipeline-failed` finding whose commit no pull request merged, or whose `pull`
read fails, is written with no `owner` (so it reaches the operator at once) and says why in its explanation; a
failed read is said and the owner is written at the next step end of that commit.
- **A-192** (ADR 0596, ADR 0603 §8, §499, §541, §520; principles 1 and 7) The builder says `wait-held` and `wait-ended`
for a key queued behind a package, in the one wait form with its `part`, and the watchman times it from those; its
reads of the builder's `builds`, the node-engine's `have` and `mesh-host.health` go, replaced by the node-engine's
`running` (with `healthy`) and its wait events.
- **A-193** (§64, §73, §373, §420, A-180, A-185; principles 2, 3 and 7) For a run: `run` writes each member's
pipeline at once (key `<member branch>.<id>.<module>`, running, no steps, `Run` its id), and the candidate's
revision places its steps by compare-and-set; `pipeline-started` is said when the steps are placed, with the
fingerprint and the candidate's revision; `run-started`'s subject names one member's module, branch and commit, or
for several the first member's module and branch and `run-<id>`; a member naming no branch is refused. The hook is
called once per candidate revision at the catalog follower's one subscription, whatever branches are followed, so
a runner following none still hears it. As §373 says, a run builds each member and its dependents: the dependents'
pipelines come from the candidate's entries whose fingerprints the members change.
- **A-194** (principle 4; §64) The indexer's state `runs` and its run candidates get tools as every kept thing does:
`indexer_runs` reads them and `indexer_run_drop` drops one by hand (its hand act written first); a run id is
`run-` and the runner's random 12-hex id, which the indexer's wider pattern accepts.
- **A-195** (§65, §266, §276, §534, §19, A-77, A-149; principles 2, 3 and 7) The runner's `pipeline` wait is a field on
each held pipeline's record (`held`: since, and the fingerprint awaited), no new state. A take-in changes the runner
when its own module's entry (its own name, A-149) gets a new fingerprint; every pipeline started after that take-in
is held. The pipelines' records are on the bus, so whichever runner holds the seat when the wait ends starts them:
the wait ends on the node-engine seat's `running` for the runner's module at the awaited fingerprint with `healthy`
true, on any node; its 30 minutes are a bound key, whose expiry starts the held pipelines and writes a finding.
- **A-196** (§553 with A-91; principle 7; the operator, 2026-11-09: merges need no approval) An empty status makes a
step `optional`, as §553 says, except the approval step: a policy that names no approval status asks the operator
nothing, as A-91 says; only a policy that names approval asks for it.
- **A-197** (ADR 0596, A-192, A-149; principles 1, 3 and 7) What only the node-engine knows of itself it raises as its
own findings through its finding writer: a have's failed or removed phase and its detail, its kept-data findings,
an unreachable tunnel, and every part of its health report (machine network, rewritten network, machine units,
relogin needed, directory used as found, node account fallback). The watchman stops reading `node-engine.have` and
`mesh-host.health` and raising those; it keeps only what it sees across parts.
- **A-198** (§677; principle 7; shared code is in mesh-sdk) The act's form, `ActDigest` and the ask's form move from
`operatorchannelclient` into mesh-sdk's `go/operatorask`, which the client re-exports, so the seat server in
`go/process` holds the gate with no import of mesh-contracts and no cycle between the two.
- **A-199** (A-185, A-193; principle 7) mesh-sdk's `ProcessReader` gains `AdoptEvent(seat, event, hear)`, a seat event
heard on the one subscription with no picture, made at once if no follower made it; meshcatalogclient's
`WireCandidatesProcess` adopts `catalog-revision` through it and hands each candidate revision to the hook.
- **A-200** (§502, A-188; principles 7 and 8) A taken-in delivery record's `milestone` is `<branch>.<source revision>`,
so the watchman ties a `record-opened` to the `take-in.taken` of that branch and source revision by its milestone;
`record-opened` gains nothing, and a record is covered only by what is late for its own revision's entries.
- **A-201** (§189, §190, A-160, A-174; principle 7) The assigner keeps a candidate's assignment graph per run (key
`run-<id>`), made when the candidate's revision is heard and dropped on that run's last `pipeline-ended`, as the
indexer keeps the candidate; the gate's `heads-replaced` drops nothing in the assigner.
- **A-202** (§31; principles 2 and 7) A pipeline's record and `pipeline-started` say their cause: an optional
`published` {artifact, version} set when a package's publish started it; a newer publish of the same artifact on
the same branch supersedes the running pipelines whose `published` names that artifact at an older version.
- **A-203** (design 46 approval mark §6, G §195, §424; principles 1, 7 and 8) The withheld path's forms: the tool
runner's announcement carries `fingerprint` (its own `MESH_FINGERPRINT`) beside `capabilities`; the node's record
gains `runner-capabilities` and `runner-fingerprint`, its merge into `capabilities` staying for placement; the
assignment half's per-node item gains `readings` and `fingerprint`, its digest over all of it, read from the node
record the assigner holds; the grants part follows the assignment half by `mesh-wants`' `revision` and its
`assignment-revision` event; its user list carries `withheld: [{module, subject, why}]`, and the seat `mesh-grants`'
verb `withheld` takes `{node}` and answers `{node, modules: [{module, subjects: [{subject, why}]}]}`.
- **A-204** (§498; principle 2) The assigner keeps which put waits it said in its own state on the bus, so a put
that ends while the assigner is stopped gets its `wait-ended` at the next start.
- **A-205** (§441, §195; principle 7) `grants-for` reads its candidate's catalog half through the catalog seat's
`revision`: for a run, with `group` `run-<id>` (the candidate's newest); for a source revision, with `branch` and a
new optional argument `source`, answering the branch's revision taken in from that source revision. It answers the
permissions the composed memberships gain and lose with the candidate's entries in place of the branch's newest.
- **A-206** (A-195, §65, §534, A-181; principles 3, 4 and 8) The runner's held pipelines are released by hand through
a seat verb `release` of `mesh-pipeline-runner` (class act, its hand act written first), beside `start` and
`ask-again`, its tool `runner_release`; the bound's expiry writes the finding `pipeline-waits` (scope `module`, id
`<branch>.<id>.<module>`); the wait's `on` gains the value `runner version`; its `clock-from` is the `build.ended`
of the awaited fingerprint, heard as A-181 says.
- **A-207** (§86, §81, §415, §71, §275, §335, §441; principles 1, 2 and 7) The runner keeps a state `recoveries`
(commit to why) written when it hears the mesh-delivery seat's `recovery-merged`, read at a pipeline's start and
resume; a recovery heard after its pipeline started asks nothing again. `widens` is computed from two reads: the
catalog seat's `revision` of the candidate against the branch's newest (the serving parts' entries and fingerprints,
found by holder from the seat list; the acting rules `step`, `on` and `bound` and the credentials the entries
declare), and the grants part's `grants-for` (the permissions); no other verb.
- **A-208** (ADR 0656, §558, §605, §16, §293, §600, §18, §104, §44-§46, A-93, A-190; principle 7) The indexer writes a
catalog entry's edges of kinds 1 to 6, as the catalog graph is its own; the long form of `invokes` is read by the
second reader release's `InvokeFields`, which G merges. Every watched branch's take-in uses the trunk's machinery,
per branch: its own pending revision (holding only that branch) and its own groups. `stepsVia` is open while the
entry's fingerprint is still in the branch's newest revision; `messageVia` while a pending entry names the merge or
a take-in of that commit runs.
- **A-209** (design 46 approval mark §13, §677, §73; principles 3 and 7) A digest in a key is escaped with mesh-sdk's
`keys.EscapeName`, the one escape form for every name in a key, in both gates: `<node>.act.<escaped digest>`. The
kind (a test's in-memory state accepting a key the bus refuses) is fixed where it lives: mesh-sdk's in-memory state
for tests refuses every key the bus would.
- **A-210** (§7, §428, A-126, A-131, ADR 0596; principles 3 and 7) A module that calls another module's tool or hears
its module events finds that module as the holder of the seat it holds, with `seatlist.HolderOf`, when it calls,
asking again after a failure and never stopping its start for it; a read of another module's bucket goes (each by
its own row). A tool's callers list names no module: it takes the holders of the seats `node-tool-runner` and
`mesh-healers` from the seat list when a call is checked, beside `operator`.
- **A-211** (A-204; principles 2 and 7) The assigner's said put waits live in a state of their own, `put-waits`
(history 1, key `<node>.<module>`, value the wait's id and the put), so no form is shared with §706's waits and the
record outlives a supersede.
- **A-212** (§47, §432, A-208; principle 8) An edge of kind 2 comes from a `needs` reference to another module's
artifact: that is what an artifact "fetches by reference at its start", so the referenced artifact is published
before the referring one delivers. Kind 5 goes to a design line (which acting steps give it, and between what).
- **A-213** (corrects A-86; §16, §354, §206) The indexer does ask node-build-go's `run` for its validation of a
revision before its take-in, as §16 says; A-86 holds only for `KeepInput`, which the indexer's `input` verb calls
for a run on request's asker. The run's input and job, what holds the pending revision meanwhile, and how a non-trunk
branch's pending revision and groups are made go to design lines.
- **A-214** (§366, §623; principle 7) `show` and `kept` read each store's fill through the bundle's state call
`mesh/state.info` (§623), as the forge module's read tool does; the runner's process writes nothing for it.
`pipeline-failed` takes scope `merge`, id the commit.
- **A-215** (§71, §275, §335, A-207; principles 3 and 7) For `widens`, the pipeline's own revision (the candidate) is
compared with the branch's newest revision: an acting rule widens when an entry's `Acts` gains a rule, or a rule's
`on` now names more, or its `bound` is longer; a credential widens when an entry's manifest names an own secret or
provision of a credential it did not name before; permissions come from `grants-for`.
- **A-216** (amends A-181; principles 2 and 7) The builder's `build.ended` stream, kept last per subject, has no age
bound, only a cap in bytes: one end per fingerprint is the record of what was built, so a module unchanged for any
time is still known built after a restart.
- **A-217** (§298, §300, A-167, A-132; principles 2 and 7) A want reverts when its fingerprint is one the module had
in an earlier assignment graph revision than the one it now runs from, by the revisions' own numbers; the running
manifest is the catalog entry of the fingerprint the node-engine seat's `running` names, read through the catalog
seat's `entry`, and `FormChanges` compares it with the want's entry.
- **A-218** (A-206, §696; principle 3) `pipeline-waits` is cleared when the node-engine seat's `running` says the
awaited runner fingerprint healthy; A-206's `runner version` holds over §696's wording.
- **A-219** (refines A-198; §677; principle 7, one form for each thing) Only `Act` and `ActDigest` move into mesh-sdk's
`go/operatorask`; the ask's types stay the generated seat contract's. The gate in `go/process` takes the operator
channel's calls (ask, read the warrant, record) as an interface its caller passes, which `operatorchannelclient`
implements over the generated types, so no form is copied and no import cycle arises. The seat client's
`wait: held` lives with `process.Conn`'s call, as there is no `go/seats`.
- **A-220** (§71, §441, A-167, A-207, A-215; principle 7) The serving parts `widens` compares are the holders of the
seats `mesh-pipeline-runner` (the runner), `mesh-catalog` (step detection), each step's own seat (the build seats
that run lint and tests) and `node-engine` (the composer, A-167), found by `seatlist.HolderOf`.
- **A-221** (§509, A-208; principle 8, one word per thing) On every forge message `branch` names the watched branch
the move changed, on `merged` as on `pushed`; a merged pull request's own branch is kept as `head` (a group is
known by its head branch); `pushed`'s head before is `before`.
- **A-222** (A-193, A-199, §350, A-77; principles 2 and 3) An adopted event whose handler fails is asked again by
the bus, not acknowledged; at its start the runner reads, for each run pipeline with no steps yet, its candidate's
revision through `revision`, so a placing lost while it was down is taken up. A run's rerun asks with the
candidate's catalog half. An unanswered drop is said `call-unanswered` on a five-minute bound key's expiry.
- **A-223** (corrects A-221; principle 8) A merged pull request's own branch is `head-branch`; `head` stays the head
commit, as everywhere in the forge messages.
- **A-224** (§677, A-219; principle 7; code shared between modules is in mesh-sdk) The approval gate is one package,
mesh-sdk `go/approval`: the tool runner's gate (`node-tools` `internal/approval`) moves there and both the tool
runner and `go/process`'s seat server use it, each passing the operator channel as an interface (A-219); no second
gate is written.
- **A-225** (A-173, §532; principles 2 and 7) The view keeps each repository's reach in its own state on the bus, so a
restart does not lose it; its history is the source revisions heard since its start, re-asked through `source` on
each `source-moved`, laid over the reach it kept.
- **A-226** (A-167, §354, §64, §63, A-174; principles 2 and 7) The composition step asks each node's
`compose-candidate` with the key the step's pipeline names: a run's candidate `run-<id>`, or for a branch pipeline
the branch's revision `<branch>.<revision>`, which the node-engine reads as it reads a candidate. It runs
`mesh-compose` once per node-engine fingerprint among the machines (the change's build where the change alters the
node-engine, §63), the program read from that fingerprint's catalog entry through `entry`, each run's request
joining the inputs of the machines on that fingerprint.
- **A-227** (withdraws A-221 and A-223; §714, §715) As design line §714 says, a merged message gains `base`, the
watched branch it landed on; `branch` stays the pull request's branch and `head` its head commit, as today;
`pushed` keeps `branch` for the branch pushed and gains `before`.
- **A-228** (A-219, A-224; principle 7) Everything the gate reads beyond itself crosses into mesh-sdk `go/approval` as
an interface in the gate's own terms, its caller translating from the generated contracts: the catalog's entries
(module, fingerprint, serves, manifest), a finding writer (raise and clear by kind and id), the seat holders (a
holder function), and the operator channel (ask, record, and claim with the warrant and the act). The gate's own
kept form `Kept` moves into `go/approval`, which `operatorchannelclient` re-exports.
- **A-229** (§708, §709; principle 7) As §709 says, a catalog entry's `requires` names every requirement as
`catalogue.Manifest.Wants` lists them, optional ones included; a reader that means "required, not optionally" (the
module graph's `Requirers`, the assigner's halves) tells the optional ones apart by the entry's manifest
(`IsOptional`).
- **A-230** (§554, §565, A-124; principle 7) A restore point's `Point` gains `names`, the bus names it took, one per
bus object as `Aside`'s; the recovery module fills it when it takes a point, and the grants part reads
`points[].names` and `asides[].names` from `kept-points`.
- **A-231** (§544, §601, A-163, A-170; principles 3 and 7) An asker names the queue it asks in its manifest's `invokes`
as `seat:<seat>.accept.<queue>`, read by one mesh-sdk `catalogue` helper that the validator, the indexer's kind-6
edge and the grants part share; every asker of a build seat gains that entry in G, so the named workers stand from
G's delivery and the purge finds nothing to remove.
- **A-232** (§712 with §600, A-163, A-170; principle 7) The validation run rides `accept.check.<asker>` with its kind
`run` in the body and the asker the indexer's seat name `mesh-catalog`, as every ask does; its id is the usual
form (`NewID`), and the revision's sequence and try number are kept in the pending value's `validation`. §712's
subject and id are read so.
- **A-233** (A-181, A-189; principle 7) mesh-sdk's `HearStream` gains a form that reads an age-kept stream whole from
its first message by an ordered consumer at every start, then follows the durable; the grants part grants that
ordered consumer on every heard seat kept stream, as it grants `STREAM.INFO`, with no manifest word.
- **A-234** (§711, ADR 0656 §6; principle 2) The indexer fills each catalog revision's `definitions` (the seat
definitions it was taken in with, by digest) when it keeps the revision, and the `acts` fill reads from them; until
then reading the trunk's from its `seat-definitions` state stands.
- **A-235** (A-201, A-174, §190, RN9; principles 1 and 7) The runner says `group-ended` with group `run-<id>` once every
pipeline it placed for the run has ended, as it says a group's end; the assigner drops its candidate graph on it, and
the indexer drops the run's candidate on it in place of counting members itself. The kept object's key stays the
seat's form `candidate.<group>.<heads>` with group `run-<id>`.
- **A-236** (§509, §714, §715, §11, A-227; principles 2 and 7) A `pushed` message's new head is `head`; the bridge
keeps each watched branch's last head written in its own state `heads` (key `branch.<owner>.<name>.<escaped
branch>`), `before` read from it and its start read comparing with it; `pushed` carries the same take-in inputs as
`merged`. For §715 the mesh-delivery seat's `groups` member gains `base` in the contract, which the gate fills and
the bridge reads.
- **A-237** (§712, §354, ADR 0666 §16, A-139; principle 7) A run's input is any size: the indexer keeps it in its state
`inputs` with the state's `-objects` store holding a large value (mesh-sdk's `stateobjects`), and serves it through
its `input` verb answered in chunks (`buscalls.SeatChunks`, a verb marked `chunks`); `RunInputBound` goes, and the
holder takes the input by that verb.
- **A-238** (§712; principle 7) A run ask may name no head: `RunJob.check` takes an empty `Heads` when the program
is named, and the holder lays an empty `MESH_RUN_HEADS`; the validation's program is built from the indexer's
entry alone.
- **A-239** (design 46 approval mark §6, H-21; principles 3 and 7) The node-engine's `composition` answer gains
`withheld` [{subject, why}] (the module's entry of the grants part's `withheld` for this node) and
`withheld-unknown`, the words "withheld unknown: the grants part does not answer" when the verb fails; its
manifest's `uses` gains `mesh-grants` beside the `invokes` of `seat:mesh-grants.withheld` H-21 added.
- **A-240** (§354, ADR 0596; principle 1) The assigner waits on its composition run's answer by hearing the build
seat's `step-ended` for that ask, never by reading the seat's step state.
- **A-241** (§712, A-234; principle 3) The validation's `seats` are the branch's revision's seat definitions (A-234)
with the merges' changed definitions laid over them, so a revision that touches no definition is still judged
against the whole seat list.
- **A-242** (§512, §186, §376, §378; principles 1, 2 and 7) The assigner's `difference` fills `Tiers` and each
change's `after` (the kind of edge that orders it), computed in its compare; the view orders nothing itself. A
`view_tiers` call for a source revision compares the kept assignment revision whose catalog for that branch is that
source revision with the revision kept before it. The view keeps a state `waits` (key owner, step, node, module)
written by its process from every part's `wait-held` and `wait-ended` it consumes, read by its own read tool.
- **A-243** (corrects A-226's joining; A-237, A-238; principle 7) The composition step runs one request per machine,
each carrying that machine's input; no inputs are joined. A-237 holds for every run's input (the assigner's and
`mesh-wants`' `input` too): any size, kept with an `-objects` store, answered in chunks. The composition run names
no head (A-238); its program is the node-engine fingerprint's entry (repository, commit, directory) with the
composer's package.
- **A-244** (§677, A-186, A-219; principles 7 and 8) `wait: held` travels as a bus header on the request, never as an
argument, so no verb's input and no act's digest changes; the holder's held answer is a reply field `held`
{asked, call} beside result, error and node. `process.Conn`'s seat call sends the header on every seat call and
waits for `gated-ended` only when the reply says `held`. A process holder applies the seat definition's
`needs-approval` alone (the definition `AnswerSeat` is given); it reads no catalog entry.
- **A-245** (§298, §368; principle 7) §298's order edges are held under the assigner's rule 7, as its acting waits
are; a change of the assigner's state forms bumps its manifest's version once, in the commit that changes them.
- **A-246** (§376, §498, A-211; principles 2 and 4) A dependent's delivery wait is kept in a state of its own,
`delivery-waits` (key the module, value the `wait-held` said), read by `assigner_waits` beside the others;
`assigner_release` {module, step: delivery} writes the hand-act log first and ends the wait `released`.
- **A-247** (§713, A-232; principles 1, 2 and 7) The pending value's `validation` gains `accepted` (the seq it was
accepted at), so a revision held for another indexer is never asked again; `validation` sits on the newest pending
value of the revision alone. The answer is read from the `step-ended` event's own output and output object, never
through the build seat's `steps`; the ask is put through the delivery SDK's `buildrun.Asker`.
- **A-248** (A-163, A-232; principle 8) `buildrun.Asker` gains the asker its subject names (the caller's seat name,
A-163), empty meaning the builder until the asker rename at the join; the ask's own `Asker` field is left as it is.
- **A-249** (A-237; principles 7 and 8) A bundle takes a chunked seat answer through its ordinary seat call: the tool
runner receives the chunks with `buscalls.SeatChunks` and hands the bundle the whole answer, so no bundle receives
chunks itself. mesh-build-go's `inputOf` calls the mesh-catalog seat's `input` that way and decodes that verb's
own answer form.
- **A-250** (§376; principles 1, 2 and 4) `assigner_delivered_again` writes the hand-act log, then an ask in the
assigner's own state `delivered-again` (key the module, value {version, by, why}) and answers "asked". The
assigner's process hears that write on its own state at once, says `version-delivered` again when every present
placing machine runs the version healthy and deletes the ask, else keeps it with its reason, read by
`assigner_waits`.
- **A-251** (§17, §383, §437; principle 8) The finding `branch-unprotected` has scope `merge`, id the owner,
repository and branch escaped as one key name (`<owner>~<repository>~<branch>`), severity warning, and that scope
and id as its subject.
- **A-252** (§354, A-167, A-174, A-226, A-243; principles 1, 2 and 7) The composition step's machines are the nodes
whose placement of the module names the step's branch in the seat's assignments (no branch read as the trunk); a
run on request on an unwatched branch takes the nodes placing the module on the trunk. Each request's cases and seats
come from the step's catalog revision through mesh-catalog's `revision` (each entry's manifest digest and verdict,
its `definitions`), depth compose, the one machine, one case `change`. A machine's node-engine build is what the
assigner keeps from the node-engine seat's own events, never read from the node-engine's bucket; where the step's
revision's node-engine entry differs from the trunk's, that build serves every machine. One run ask per machine.
- **A-253** (A-249; principle 8) The tool runner hands a bundle a chunked answer as the verb's own answer with the
whole file added as the member `file` (base64).
- **A-254** (§712, §354, A-240, A-247, ADR 0596; principles 1, 2 and 7) A build seat's `step-ended` of a run carries
the run's answer (its standard output's last line): inline as `output` up to the event bound, else as
`output-object`, the name of an object the build seat keeps, read through the seat's verb `output` answered in
chunks. Every build seat (`node-build-go`, `node-build-image`, `node-build-node`) says it the same way, from the
shared step runner; no asker reads the seat's step state.
- **A-255** (§677, A-77, A-244; principles 1, 7 and 8) The header is `x-wait: held`. A process holder's
`gate-unanswered` is a bound key with its time to live in the `approvals` state, as the tool runner's `bound` is,
never a clock wait. A process holder's act names no node, so two instances of the holder raise one ask.
- **A-256** (corrects A-251's separator; principle 8) The finding's id is the owner, repository and branch joined by
`/` and escaped as one key name (`keys.EscapeName`); a key holds no `~`.
- **A-257** (A-249, A-253, A-254; principles 7 and 8) The tool runner sends a bundle's answer of a verb marked
`chunks` in chunks, from the whole file the bundle answers in its member `file`, the mirror of A-249: no bundle
sends chunks itself.
- **A-258** (§298, A-210; principles 1 and 8) §298's "bus module" is the holder of the seat `mesh-broker`, and its
"`node-backup` holder" the holder of the seat `node-backup`, each read from the seat list as every holder is: the
assigner names no module.
- **A-259** (§298, A-245, §266, §268; principle 7) §298's three order edges are acting waits of the assigner, kept
in its state `waits` under `order.<node>.<module>.<part>` beside `acting.`, said as `wait-held` when the want is
held and `wait-ended` (ran, released, replaced) when it moves, with the step `placing`; `assigner_waits` reads
them and `assigner_release` releases them as it does the acting waits. No new mechanism.
- **A-260** (§298, ADR 0633 §1, A-181; principles 1 and 7) For §298's third edge the trunk's head is the highest
source revision (`Src`) among the trunk branch's module values the assigner holds; the wait ends when a
`take-in.taken` of the trunk branch with `source` at or above it is heard. The assigner consumes
`mesh-delivery-indexer.take-in.taken` (a `consumes` entry), heard as it hears `build.ended`; a wait still held
after a restart is said again as `wait-held` and ends at the next such take-in.
- **A-261** (A-252, A-234; principles 2 and 3) A composition request's `Seats` carry, for each (seat, digest) of the
step's catalog revision, the definition whose digest it is: from the revision's `definitions` once A-234 fills
them, until then from mesh-catalog's `seat-definitions` where the trunk's digest matches; a digest neither holds
ends the step `could not run`, naming the seat and the digest.
- **A-262** (§496; principles 1 and 7) The assigner says a running composition step's progress once a minute with a
ticker inside the running step, stopped at its end, as mesh-delivery-sdk's `steprun` says its own beat (pull.go);
no bound key and no new key form.
- **A-263** (§712, §676; principles 7 and 8) §676 writes `package` (the Go module its `go.mod` names) for every Go
artifact, a `bundle` too, since a bundle is built from that Go module; §712 reads it there.
- **A-264** (§677, §697, A-186; principle 7) The event `gated-ended`, the verb `approvals` and the by-caller form of
a marked verb are added in mesh-sdk's `seatdef.Resolve`, which the seat generator and every reader of a definition
(the seat list, the grants part, the validator, `AnswerSeat`) go through: one place, one definition for all; the
seat files stay as written.
- **A-265** (A-264, design 46 approval mark §20; principles 4 and 7) A-264 holds for every marked definition. Where a
tool bundle holds the seat (the login shell's `execute`), the tool runner, which already holds that bundle's gate,
answers the marked verb by caller and serves `approvals` for the seats its bundles hold, as `AnswerSeat` does for a
process; no holder changes and no mark moves.
- **A-266** (A-264, A-265, ADR 0132; principle 7) `approvals` is the gate's verb, served wherever a marked verb is:
`CanHold` and the validator's same rule ask no holder to name it in its claim's `serves` or its tools.
- **A-267** (§496, §481, §22, A-170; principle 7) The composition step's `step-progress` carries `asker` `runner`, the
one asker that sends the accepted kind `step` on `mesh-wants`; the asker rename after join 11 (A-163, A-170) reads
it from the accept subject's asker token instead.
- **A-268** (corrects A-263; §712, §676, §491; principle 7) §676's `package` stays for package artifacts only, since a
bundle's Go module named as a package collides under §491's package names when two modules share one `go.mod`.
§712's job names the indexer entry's repository, `path` and the revision's head, and the program's directory;
`mesh-build-go` reads the Go module from the `go.mod` it builds there, as it does for every build.
- **A-269** (§509, §714; principles 7 and 8) A `pushed` message's `head` stands where a `merged` message's `merge`
stands: pending refs, the newest load and the revision's head key on it alike.
- **A-270** (A-255, §677; principles 3 and 7) A holder's approvals state is declared with `key-ttl` beside §677's
48 hours and 64 MiB, since its bound keys `unanswered.<call>` need it; the validator refuses a holder of a marked
verb whose approvals state lacks it.
- **A-271** (A-265, §677; principle 7) The tool runner's `approvals` answer has the form of `AnswerSeat`'s, read from
the runner's own record of the calls its gate holds; it keeps no `call.` keys of its own for it.
- **A-272** (§677, ADR 0596; principle 1) The `GateChannel` over `process.Conn` asks and reads an ask only through
mesh-sdk's `operatorchannelclient` on the seat `operator-channel`, never through the router's bucket.
- **A-273** (corrects A-272; §700, A-74, A-89; principles 1 and 7) The `GateChannel` over `process.Conn` is §700's:
`operatorchannelclient.Client` given, as its `Record`, a get of the key under `<module>.` in the seat
`operator-channel`'s state `asks` (the bucket formed from the seat's holder on the seat list and `StateAsks`, A-74)
on the process's own connection; the verb `asks` stays as it answers. The ask is published by a new `go/process`
method that publishes on a seat's accept subject (`mesh.seat.<seat>.accept.<queue>.<caller>`), on the a3g line,
as `Emit` publishes an event.
+1
View File
@@ -104,5 +104,6 @@ The part is eighteen files, each read whole, its design lines numbered across th
- [G-18-fix-round-six-seven](G-18-fix-round-six-seven.md): the fix round of §587 to §676: the approval mark once no verb names its callers, the keeper's snapshots, the recovery module's verbs, the node-engine's kept entries, the gate before a marked verb's running, develop's D-16 to D-49, and a delivery's wait on another machine's network (§677 to §705).
- [G-19-outside-wait-and-refusals](G-19-outside-wait-and-refusals.md): a delivery's wait on an outside cause, written whole once (§706, in place of §705), and the finding writer's own refusals in every bundle (§707, amending §580).
- [G-20-lead-answers](G-20-lead-answers.md): the lead's one-line answers to develop's questions, each tested against the principles (A-1 on).
- [G-22-lead-answers-2](G-22-lead-answers-2.md): the lead's answers continued, from A-182.
Design 34's milestone [every-event](../34-milestones/every-event.md) and design 46's milestone [7-approval-mark](../46-milestones/7-approval-mark.md) ship in milestone G's release, built in its repositories beside G's lines (lead-47, 2026-11-11 15:30 CET); where one of their lines and a line of G differ, G's later line holds and the other is corrected in place (§624 to §626).