Design 47 G: answer develop's questions against the principles; the outside-cause wait whole (G-19); lead answers (G-20) #553

Merged
mesh-tools merged 8 commits from design/47-G-develop-answers-7 into main 2026-11-11 20:54:19 +00:00
10 changed files with 302 additions and 62 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ operator; never build otherwise.
**A question the design does not answer stops that subtask.** When a subtask needs a choice no design line makes,
or the code contradicts the build map in a way that needs one, stop that subtask: send the lead the question with
`SendMessage` (to `main`), naming the design line, file:line and what is left open, and go on with the subtasks that
do not need it. Never guess it, build around it or build both ways; an answer counts only once an hq commit holds it.
do not need it. Never guess it, build around it or build both ways; an answer counts only once an hq commit holds it: a design line, or the lead's one-line answer in the milestone's lead-answers file, which names the principle (`00-META/principles.md`) that settles it.
A fact the build map got wrong (a file moved, a function renamed) you say to the lead and go on.
**How you work.** Worktrees from `origin/main` on the branch the handover names, subtasks in the build map's order:
+9 -3
View File
@@ -295,6 +295,12 @@ controller and the store; for module assignment, by the seat `mesh-module-assign
again on the callee's event saying its answer changed (§4). mesh-sdk carries its form (§7). A call not marked is
made once and its fault said.
*Not:* ~~retried call~~ (hq)
- **waiting call** — a module's call of a marked verb that the verb's holder keeps whole, with the caller the bus
proved and its ask, until the operator's answer: on the Approve the holder runs it once, and it says the call's end
(ran, declined, expired or refused) on its seat's event `gated-ended` to that caller alone (ADR 0676 §2, §3). The
caller calls once and may not mark it safe to repeat; only its wait for the end is kept. Unlike a kept call, it is
never called again.
*Not:* ~~gated call~~ (hq)
- **the deprecated broker** — the lavinmq module. It was the mesh's bus and is not any more. It keeps
running as an **ordinary provider** of the `amqp` provision, for modules that need a message broker
of their own the way something needs a database
@@ -1124,9 +1130,9 @@ asking, never the act. **Decided by** ADR 0152, 0175, 0234, 0259, 0272, 0383, 03
0274), a trusted config value (ADR 0277, ADR 0348).
A proposal changes nothing by itself; declined, expired or refused, it is discarded.
- **approval mark** — a tool's or verb's declaration in its manifest (`needs-approval`) that each call to it runs
only on the operator's warrant for that one call, with its exact arguments; the tool runner that serves it, or
the controller for its own verbs, asks and checks
(ADR 0286). It covers a module's events and streams too (the operator, 2026-11-11; design 34 every-event §32): a
only on the operator's warrant for that one call, with its exact arguments; the tool runner that serves it, the
controller for its own verbs, or the holder of a marked verb served from a module's process (ADR 0676 §1) asks and
checks (ADR 0286). It covers a module's events and streams too (the operator, 2026-11-11; design 34 every-event §32): a
module may mark one of its events, a restricted stream is marked whole, and a `mesh_wait` on a marked event runs
only on the operator's warrant for that one wait, with the exact names it waits on and its bound, which the tool
runner asks and checks before it subscribes. The tool runner reads every mark from the catalog half on the bus
+30
View File
@@ -0,0 +1,30 @@
---
status: canonical
updated: 2026-11-11
---
# The principles
A short, living list. Every question met while building is tested against these principles and answered by the
lead in one line; only a question no principle settles goes to the operator or to a decision record. A detail that
a principle settles is not written down as a design line or a record. The list changes when the operator says so:
add, sharpen or drop a principle in a pull request to this file.
1. **NATS-native.** Every interaction between modules is an event, or a call over the bus where an answer is
needed. A module keeps its data in the bus's own storage, and reads another module's data only by asking it,
through its verbs or its tools.
2. **The mesh owns the truth.** State lives in the mesh and is written onto the nodes from there. Nothing is changed
by hand on a node.
3. **Failure is loud.** Nothing reports success when it did nothing, and nothing fails silently. When in doubt, fail.
4. **A module is steered by its tools.** Everything a module holds can be read, everything it does can be started
by hand, and everything that goes wrong can be recovered, all through its tools.
5. **Everything ships the same way.** The mesh's own parts go through the same build, check and delivery as any app.
6. **Nothing is exposed publicly.** No data leaves the mesh unasked: no secret in a record, a log or a public
repository, no service reachable from outside unless it is meant to be. Inside the mesh, every agent and module
is trusted; who may do what is not a question to ask.
7. **The simplest thing that works.** Prefer what already exists. No new mechanism unless it is needed, and fewer
parts over more.
8. **One word per thing**, from the [glossary](glossary.md).
How it is checked: the one code review of a milestone checks the code against these principles and the design's
shape; an answer to a develop question names the principle that settles it.
@@ -530,7 +530,8 @@ form only. A note that corrects a line of G-12 or G-14 is written in that line;
## Observers with more than one bundle, and the forge module's forms
- §580 **Each finding kind belongs to one bundle, and a statement covers only its own kinds.** (§383, §384, §485)
- §580 **Each finding kind belongs to one bundle, and a statement covers only its own kinds.** (§383, §384, §485;
the writer's own kind `finding-refused` and the statement's `bundle`: §707)
A module whose bundles write one state `findings` (the forge module has four: its TypeScript tools, its Go package
registry, its forge and its agent token) gives each finding kind to exactly one bundle. That bundle's mesh-sdk
writer is made with the kinds it owns, and refuses a `write` or a `clear` of any other kind, naming it. Each bundle
@@ -5,6 +5,7 @@ design: 47
milestone: G
updated: 2026-11-11
decisions:
- "ADR 0676"
- "ADR 0674"
- "ADR 0673"
- "ADR 0672"
@@ -38,13 +39,13 @@ One file of milestone G's part of [design 47](../47-delivery-from-commit-to-deli
2026-11-11): the approval mark once no verb names its callers (the operator's answer of about 16:10 CET, §610); the
keeper's snapshots, with the operator's answer O-7 of 20:22 CET (§681); the recovery module's verbs, the entries the
node-engine keeps and the grants part's first composition (§682 to §684); the gate before a marked verb's running
(§677, the operator's O-8); develop's D-16 to D-49, of internal form only; and the operator's O-9 (§705). The rounds' other fixes are written in the lines they correct.*
(§677, the operator's O-8); develop's D-16 to D-49, of internal form only; and the operator's O-9 (§705, written whole in §706). The rounds' other fixes are written in the lines they correct.*
## The approval mark, with no named callers
- §677 **A marked verb a module's process serves is one call with a gate before its running, asked, checked and
claimed by its holder alone.** (§610; ADR 0676; ADR 0286 §10 to §13, §24, §26 to §31, §35, §36, §38, §43; ADR 0259
§3, §6) Once no verb names its callers (§610), a module's process may call a marked verb (ADR 0286 §1, §2)
claimed by its holder alone.** (§610; ADR 0676 §1 to §7; ADR 0286 §6, §10 to §13, §24, §26 to §31, §35, §36,
§38, §43; ADR 0259 §6) Once no verb names its callers (§610), a module's process may call a marked verb (ADR 0286 §1, §2)
directly. Design 46 7-approval-mark's gate wraps only the handlers the tool runner serves (its §20); a marked verb a
module's process serves is judged by that process, as ADR 0286 §43 has the controller judge its own verbs, whoever
calls it. The operator, 2026-11-11 about 20:40 CET at lead-47's terminal (O-8): "the tool call should be the same,
@@ -53,7 +54,7 @@ node-engine keeps and the grants part's first composition (§682 to §684); the
manifest validator refuses a TypeScript process that serves a marked verb, and the seat generator makes every
marked verb `by-caller` (§697).
- **Refused before anything is kept.** A call whose arguments hold anything shaped like a secret or pass 16 KiB is
refused at once, asking nothing and keeping nothing (ADR 0286 §12).
refused at once, asking nothing and keeping nothing (ADR 0286 §12; ADR 0676 §1).
- **The holder keeps the call and asks, under its own module's name.** Otherwise mesh-sdk's seat server makes the
act as ADR 0286 §10 and §11 make one (the address as called, the holder's own node and build, the seat and verb,
every argument, digested with `operatorchannelclient.ActDigest`), and finds or raises its ask through the key
@@ -62,36 +63,37 @@ node-engine keeps and the grants part's first composition (§682 to §684); the
the create succeeds; an instance whose create fails reads the key and takes that ask, so two instances raise one
ask; a key whose ask has ended is replaced by compare-and-set on its revision. When the call says `wait: held`
(below), the holder keeps it as a waiting call of its own, `call.<id>`, `<id>` 128 random bits, holding the call
whole, the caller the bus proved and its ask (ADR 0286 §24), and answers at once `{asked: <ask id>, call: <id>}`.
whole, the caller the bus proved and its ask (ADR 0286 §24; ADR 0676 §2), and answers at once `{asked: <ask id>, call: <id>}`.
- **A second call of the same act.** Every call is kept as its own `call.<id>`, whoever makes it; one made while
that act's ask is open takes the same ask (ADR 0286 §13, §23, §38) and its answer names that ask and its own
call. On the Approve the oldest kept call of the act runs; each other kept call of the act is asked anew at once,
that act's ask is open takes the same ask (ADR 0286 §13, §23, §38; ADR 0676 §4) and its answer names that ask and its own
call. On the Approve the oldest waiting call of the act runs; each other waiting call of the act is asked anew at once,
as a new ask of that act (ADR 0286 §33: a second run takes a second approval), and its end comes when its own ask
ends.
- **On the Approve it runs that same call.** When the holder hears its own `operator-channel.decided` of the ask, it
reads the router's own record of the ask under its module's name, on the one path §700 names, never the decided
event's body nor the caller's word (ADR 0286 §26, §36), holds the warrant to it with `Warrant.For` and
`Option.Performs` against the kept call (ADR 0286 §27, §28), claims it once (below), runs the kept call, once, and
event's body nor the caller's word (ADR 0286 §6, §26, §36; ADR 0676 §3), holds the warrant to it with `Warrant.For`
and `Option.Performs` against the waiting call (ADR 0259 §6; ADR 0286 §27, §28), claims it once (below), runs the
waiting call, once, and
records the run in the hand-act log of the seat `mesh-hand-acts` as a kept call until it is taken (ADR 0286 §35,
ADR 0668 §1). The kept call runs only within 30 minutes of the choice; heard later (the holder away meanwhile),
ADR 0668 §1). The waiting call runs only within 30 minutes of the choice; heard later (the holder away meanwhile),
it ends `expired` and runs nothing (ADR 0286 §29). After a Decline the same act is not asked again for 10
minutes: a call of that act within them ends `declined` at once, with no ask (ADR 0286 §38).
minutes: a call of that act within them ends `declined` at once, with no ask (ADR 0286 §38; ADR 0676 §4).
- **The caller hears the outcome on its own call's subject.** The holder says the call's end on its seat's event
`gated-ended`, subject `mesh.seat.<seat>.event.gated-ended.<caller>.<call>`, `<caller>` the account the bus proved,
escaped as a key's name is (§73): `{call, ask, act, verb, outcome, answer, error}`, `outcome` one of `ran` (with
the verb's `answer`, and in its own field `approval` the line naming the approval, ADR 0286 §34), `declined`, `expired` and `refused` (with the router's or the check's words); a decline or
an expiry runs nothing and says so. Kept last per subject, one day, and no argument is in it: a caller down for
an expiry runs nothing and says so (ADR 0676 §2). Kept last per subject, one day, and no argument is in it: a caller down for
longer than a day loses that outcome, and reads the holder's `approvals` verb (below) for it. Every seat
definition with a marked verb gains the event through the seat generator; the grants part grants hearing
`gated-ended.<caller>.>` to that caller alone, from its `invokes` of the marked verb by name, as it composes a
`gated-ended.<caller>.>` to that caller alone (ADR 0286 §6), from its `invokes` of the marked verb by name, as it composes a
`by-caller` verb. mesh-sdk's seat client, in `go/seats` beside the seat server, sends `wait: held` on every call
of a marked verb, waits as a kept wait (ADR 0668 §1) on its own `<call>` alone and reads it at its start, so a
restart of either side loses no outcome; it makes no second call. A module may not mark its call of a marked
verb safe to repeat (ADR 0668 §2): only the wait on `gated-ended` is kept. The calling module holds no warrant,
and the holder asks once per call; `mesh-delivery.release` stays unmarked (ADR 0286 §46), so ADR 0286 §47's
question is closed.
question is closed (ADR 0676 §7).
- **A person through the tool runner keeps ADR 0286 §37's path for now.** An MCP call cannot be held for an ask's
60 minutes (O-8); this "for now" is tracked by issue 417. A call that does not say `wait: held` (the tool runner sends none) is answered with ADR 0286
60 minutes (O-8; ADR 0676 §5); this "for now" is tracked by issue 417. A call that does not say `wait: held` (the tool runner sends none) is answered with ADR 0286
§37's refusal naming the ask and keeps no call, its ask found and written through `act.<digest>` as above, so the
same call made again after the Approve finds that ask, is checked as above, claimed and run. `wait` is no
boundary: either path runs the act only on the operator's warrant for that act, claimed once, so a module that
@@ -99,13 +101,13 @@ node-engine keeps and the grants part's first composition (§682 to §684); the
- **The holder claims, once, in its own state.** The holder's template state `approvals` (a `requires` entry, 48
hours to live, 64 MiB) keeps `call.<id>`, `act.<digest>` and `claimed.<ask id>`, the claim, written with the
bus's create, which refuses a key that exists, so a warrant runs one call, on one instance or two (ADR 0286 §30,
§31). At its start the holder reads every kept call and acts on each ask already decided as above. A call kept
past its ask's 60 minutes with no decided heard raises the holder's finding `gate-unanswered` (scope the holder,
§31; ADR 0676 §3). At its start the holder reads every waiting call and acts on each ask already decided as above. A waiting
call past its ask's 60 minutes with no decided heard raises the holder's finding `gate-unanswered` (scope the holder,
id the call), cleared when its end is said. The manifest validator refuses a module that serves a marked verb from
a process and declares no such entry. A state that cannot be read or written refuses every marked call of that
holder, said as ADR 0286 §40 has it.
- **Its read.** Every seat with a marked verb gains the verb `approvals` (class `read`, its default), served by the
seat server: the kept calls with their caller, ask and state, the `act.` keys and the claims, never an argument
seat server: the waiting calls with their caller, ask and state, the `act.` keys and the claims, never an argument
of a call it was not asked by that call's caller.
- **A holder that does not check is never reached.** The grants part composes, for a module's process that serves
a marked verb, the subscription of that verb's subjects only when the catalog graph entry of the build its want
@@ -113,7 +115,7 @@ node-engine keeps and the grants part's first composition (§682 to §684); the
validator with, so a G holder is granted before it subscribes; otherwise it composes the subscribe deny design 46
7-approval-mark §6 composes for a runner that does not state `approval-mark/1`, named in `withheld` with "its
holder checks no warrant". So a holder of before G serves none of its marked verbs until its G version runs, and
nothing runs unchecked. This changes ADR 0286 §7 and §8 for a process holder (ADR 0676).
nothing runs unchecked. This changes ADR 0286 §7 and §8 for a process holder (ADR 0676 §6).
Why: the operator's answers O-6 and O-8; the holder alone can read the router's record of an ask made under its
own name (review rounds 2 and 3). How it is checked, as cases of the seat server's one whole test (a fixture marked
@@ -121,11 +123,17 @@ node-engine keeps and the grants part's first composition (§682 to §684); the
on `gated-ended` by that caller and no other; a repeated identical call kept as a second call, asked anew after the
first runs, each waking on its own `<call>`; two callers of one act, one ask, one run, the second asked anew; two
instances of the holder raising one ask and one claim, a race of two at `claimed.<id>` running once; a decline and
an expiry run nothing; a restart of the holder between the ask and the Approve runs the kept call once; a warrant
replayed runs nothing; a call within 10 minutes of a Decline ended `declined` unasked; a kept call heard 31
an expiry run nothing; a restart of the holder between the ask and the Approve runs the waiting call once; a warrant
replayed runs nothing; a call within 10 minutes of a Decline ended `declined` unasked; a waiting call heard 31
minutes after its choice ended `expired`; a secret-shaped argument refused unkept; a call with no `wait` refused with the ask and run
on the same call made again; unit (grants part), a holder whose wanted entry declares no `approvals` composed with
the deny and named in `withheld`, one that declares it granted before it runs.
on the same call made again; a decided event whose body was altered runs nothing, the holder reading the router's
record; a warrant whose act is not the waiting call's runs nothing; the run found in the hand-act log; the `ran`
end read with its `answer` and its `approval` field, and the `refused` end with the router's or the check's words;
the outcome gone from `gated-ended` after one day; a caller holding a warrant of its own for an ask of its own still
asked (ADR 0676 §7); unit (seat client), the module's call client never marks its call safe to repeat; unit
(manifest validator), a module serving a marked verb from a process with no `approvals` entry refused; unit (grants
part), a holder whose wanted entry declares no `approvals` composed with the deny and named in `withheld`, one that
declares it granted before it runs.
## Develop's D-16 to D-18
- §678 **The forms of a finding's `owner` and `waiting-on`.** (§451, §540, §580) Each is one of three forms, written as
@@ -524,36 +532,5 @@ node-engine keeps and the grants part's first composition (§682 to §684); the
## The operator's O-9: a delivery waits on another machine's network
- §705 **A machine whose network names an outside cause holds the delivery there as a wait, not a failure.** (ADR
0241 §25 to §27; the main file's *A failure is held on the canary and fixed forward*; §498, §633) The operator,
2026-11-11 about 21:05 CET at lead-47's terminal (O-9): a delivered module's own failing health check is the
delivery's; but while the machine's network statement names an outside cause, the delivery waits on that machine,
says from the start what it waits on, judges again once the cause clears and goes on by itself, and after 30
minutes asks the operator to go on or count it as failed. Where the assigner judges a node's health after a want
moves (the canary rule and its hold):
- **An outside cause.** While the node-engine of that machine says a finding `rewritten` naming a file of a module
the delivery did not move (ADR 0241 §25), or `unreachable` toward another machine (ADR 0241 §25), heard by the
assigner's consumer of the node-engine's finding events (§627's stream, in its `consumes`), a failing health check
of a module the delivery moved there is no failure: the assigner holds that move as a wait, said at once on
`mesh-wants`' `wait-held` with `step` `delivery`, `node` that machine and `on` `rewritten:<owner>` or
`unreachable:<machine>`, and writes the finding `delivery-waits-outside` (scope `delivery`, id
`<node>.<module>`), naming the cause.
- **It goes on by itself.** When that finding is cleared, the assigner judges the module's health there again:
healthy, the delivery goes on, `wait-ended` with `how` `cleared`; failing, it is the delivery's failure, held as
the canary rule has it.
- **The bound and the ask.** Past `outside-wait-minutes` (a setting, §633, 30 unless set) from the wait's start,
the assigner asks the operator through `operatorchannelclient`, `about` `<node>.<module>.<fingerprint>`, with
two options, Go on (the module counted healthy there, so the delivery goes on, `how` `go-on`) and Count as
failed (held as the canary rule has it, `how` `failed`); the ask names the cause and since when; the wait stands
until the answer or the cause clears, which ends the ask. The finding clears when the wait ends.
- **What stays the delivery's or the machine's.** A `rewritten` naming a module the delivery moved is that
module's failure (ADR 0241 §26). A machine's own `network` finding holds the machine as a whole: no want moves to
it until it clears (ADR 0241 §27).
Why: the operator's answer O-9; ADR 0241 §25 had the wait with no bound, which this gives one and an ask, resting on
the record of the outside-cause wait (number to come; its draft is with lead-47), which changes ADR 0241 §25 and
keeps §26 and §27. How it is checked, as cases of the assigner's whole test: an `unreachable` toward
another machine turning a failing check into a wait, said at once, ended `cleared` and the delivery going on when
it clears; one that fails once cleared held as a failure; past the setting the ask, Go on ending `go-on` and Count
as failed ending `failed`; a `rewritten` naming a moved module failing at once; a machine's own `network` moving
no want to it.
0677) The operator's answer O-9 of 2026-11-11 about 21:05 CET; the line is written whole in §706 (G-19), which
replaces what stood here.
@@ -0,0 +1,159 @@
---
layer: to-be
status: in-progress
design: 47
milestone: G
updated: 2026-11-11
decisions:
- "ADR 0677"
- "ADR 0668"
- "ADR 0603"
- "ADR 0596"
- "ADR 0564"
- "ADR 0539"
- "ADR 0429"
- "ADR 0241"
---
# 47, milestone G: a delivery's wait on an outside cause, and the writer's own refusals
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".
*§706 and §707 come from the review by architectural domain of lead-47's batch 8 (round 1, 2026-11-11 about 21:20
CET). §706 writes the operator's O-9 whole, once, in place of §705: what counts as an outside cause, when it is
judged, every way the wait ends, its event, its finding and its tools. §707 amends §580 for the finding writer's own
refusals.*
## A delivery's wait on an outside cause
- §706 **A failing check on a machine whose network names an outside cause is a wait that ends by itself, and asks
the operator after 30 minutes.** (ADR 0677 §1 to §4; ADR 0241 §11, §13, §16 to §21, §25 to §27; ADR 0564 §2, §3,
§13; ADR 0596; ADR 0429 §6; ADR 0539 §18; ADR 0668 §1; ADR 0603 §11; §276, §461, §498, §512, §633, §700) The
operator, 2026-11-11 about 21:05 CET at lead-47's terminal (O-9): a delivered module's own failing health check is
the delivery's; while the machine's network names an outside cause, the delivery waits on that machine, says from
the start what it waits on, judges again once the cause clears and goes on by itself, and after 30 minutes asks the
operator to go on or count it as failed. Where the assigner judges a node's health after a want moves (the canary
rule and its hold, ADR 0429 §6, ADR 0539 §18), for a module the delivery moved to a machine M:
- **Where the causes are said.** The node-engine only states M's network in its health report (ADR 0241 §13). The
watchman, holding `mesh-watchdogs`, raises the network findings from every machine's report together (ADR 0241
§16 to §21, observed by it under ADR 0564 §2), and the condition keeper, holding `mesh-conditions`, holds them as
conditions, never held while a module is delivered (ADR 0564 §13 (e)). The assigner hears them only through the
seat `mesh-conditions`: its verb `conditions` and its events `condition-raised`, `condition-changed` and
`condition-cleared` (ADR 0564 §3), named in its `invokes` and `consumes`; it never reads the watchman's `findings`
nor the keeper's state (ADR 0596).
- **What counts as an outside cause for M**, read from a condition's `key`, `raised` and subject (`machine`,
`also`), the key being the only source of an owner (a finding has no owner field):
- `machine.M.<owner>.rewritten`, or `machine.M.rewritten` (a file of no module), whose `<owner>`, the key's
part between M and `rewritten`, is no module the delivery moved to M (ADR 0241 §17, §25; ADR 0677 §1);
- `machine.<x>.unreachable` for another machine `<x>` whose `also` lists M, the machines whose failing parts
point at `<x>` (ADR 0241 §19, §21, §25; ADR 0677 §1);
- `machine.<x>.network` or `machine.<x>.silent` for another machine `<x>` whose `also` lists M: when `<x>` is
down on the record by its own network or its silence, the watchman raises no `unreachable` for it and holds
M's failures toward it under `<x>` (ADR 0241 §20, §21). The watchman (mesh-delivery's
mesh-delivery-watchman) therefore lists in `also` of those two findings the machines whose failing parts point
at `<x>`, as it lists them on `unreachable`; today it names them only in the `network` finding's summary and
not at all on `silent`. A change of `also` rewrites the finding (ADR 0564 §2).
No other condition is one. A `machine.M.<owner>.rewritten` whose `<owner>` the delivery moved to M is that
module's failure (ADR 0241 §26; ADR 0677 §3), and M's own `machine.M.network` holds M as a whole (below); neither
takes this wait.
- **When it is judged.** When a moved module's check fails on M, the assigner reads M's open conditions through
`conditions` with `scope` `machine` and `machine` M, which answers each condition whose subject's `machine` is M
or whose `also` lists M (ADR 0564 §3), as a kept call (ADR 0668 §1). It is read at each judging, never kept as a
copy from the events, since the keeper says no event when only a condition's `also` changes (it says
`condition-changed` for a severity, a resolver, a silence or its words). With an outside cause open, the move
waits. With none open, the assigner settles: it holds its judgement for `outside-settle-seconds` (a setting,
§633, 90 unless set) from the failing check, judging again on each `condition-raised` whose subject's `machine`
is M or whose `also` lists M, since the node-engine states the failing check and the network in one report while
the condition rises only after the watchman's two looks and the keeper's take-in; past it with still none, the
failure is the delivery's, held as the canary rule has it. The settle says no `wait-held`; `assigner_waits` shows
it as `settling` with its end.
- **When the keeper does not answer.** While the read of `conditions` is unanswered, the move waits `on`
`conditions-unread`, said and bounded as below, and is judged when the kept call is answered. A module that holds
`mesh-conditions` itself, as the assignments name, is judged with no read: its failing check is its delivery's
failure after the settle, since the keeper cannot answer for its own failing check.
- **The wait.** The assigner holds that move as a wait, says `wait-held` on `mesh-wants` with `step` `outside` (a
value added to §498's list, apart from a dependent's `step: delivery`), `node` M, `module`, `fingerprint`, `on`
(`rewritten:<owner>`, `rewritten` for no owner, `unreachable:<x>`, `network:<x>`, `silent:<x>` or
`conditions-unread`), `bound` (`outside-wait-minutes`, a setting, §633, 30 unless set) and `clock-from`, the
wait's first start. When the wait stands on another cause, it says `wait-held` again with the new `on` and the
same `clock-from`, so the bound is never restarted (ADR 0677 §2). It writes, through mesh-sdk's finding writer
(§461), the finding `delivery-waits-outside` (scope `delivery`, id `<node>.<module>`), severity `warning`, its
summary naming the module, M and the cause by its condition's key, its `needs` "Nothing for you to do.": a
warning that needs nothing is not sent (design 45, the router's *When*), so the operator's one message is the ask
at the bound. The watchman writes no `delivery-waits` for `step: outside`, so no second condition rises for it.
- **Judged again.** A waiting move is judged again, reading M's conditions as above, on: the `condition-cleared`
of its cause's key; each `condition-raised` or `condition-changed` whose subject's `machine` is M or whose
`also` lists M; each change of that module's have on M; the kept call answered, for `conditions-unread`; and the
assigner's start, for every wait it holds. A `condition-cleared` of a key no wait names is dropped. M leaving an
`also` with nothing else changing says no event: it is heard at the next of these, or at the ask.
- **How it ends**, each said on `wait-ended` with its `how`, the finding cleared at once:
- `healthy`: the module runs healthy on M, the cause open or not; the delivery goes on.
- `cleared`: judged again after its cause cleared, healthy; the delivery goes on.
- another outside cause open at a judging: no end; the wait stands with the new `on` (above).
- `own-failure`: judged again failing with no outside cause open, after the settle; it is the delivery's
failure, and only then does the canary rule hold it (ADR 0677 §1).
- `go-on` or `failed`: the operator's answer to the ask (below), or a release by hand with that `how`.
- `replaced`: a newer want of that module on M replaces the waited one; its own move is judged afresh, and an
open ask is ended.
- **The bound and the ask.** Past `outside-wait-minutes` from `clock-from`, the assigner asks the operator through
`operatorchannelclient`, `about` `<node>.<module>.<fingerprint>`, naming the cause and since when, with two
options: Go on (the module counts healthy there by the operator's word, and the delivery goes on, `how` `go-on`)
and Count as failed (held as the canary rule has it, `how` `failed`) (ADR 0677 §2). It reads the answer from the
router's record of the ask under its own name, on §700's path, never from the decided event's body nor a
caller's word. The wait's end ends the ask. An ask that ends unanswered is raised again at once while the wait
stands. `how` `go-on` is recorded as such, so a Go on is never read as a passed health check.
- **M's own network.** A machine whose own `machine.M.network` is open is held as a whole: no want moves to it
until its `condition-cleared` is heard (ADR 0241 §27; ADR 0677 §3). The assigner keeps that set from its
consumer of the three events and from a read of `conditions` with `scope` `machine` at its start; while that
read is unanswered, wants move as if none were held, since the keeper is itself delivered by wants moving, and a
failing check there meets the judging above.
- **Its tools** (§276's row *delivery on an outside cause*): `assigner_waits` reads each outside wait, settle
included, with its module, M, fingerprint, cause key, `on`, `clock-from`, `bound`, its ask's id and its state;
`assigner_release` takes one with `how` `go-on`, `failed` or `rejudge` (judge it again now) and a `why`, class
`act`, its default, and writes the hand-act log of the seat `mesh-hand-acts` first (ADR 0603 §11).
Why: the operator's answer O-9 and ADR 0677; the review's round 1 asked the mechanism once and whole: the watchman
holds a machine's failures toward a machine down on the record under that machine (ADR 0241 §20), so the
commonest cause, a hub silent or its own network open, is a `network` or `silent` finding and needs M in its
`also`; the keeper says no event for `also` alone, so the read at each judging is the truth, and the settle covers
a condition rising after the check it explains. How it is checked, as cases of the assigner's whole test (a
fixture keeper answering `conditions` and saying its three events): an `unreachable` whose `also` lists M turns a
failing check into a wait said at once with `on` `unreachable:<x>`, `bound` and `clock-from`, and ends `cleared`
on its clearing; one whose `also` does not list M leaves the failure the delivery's; a hub silent and a hub whose
own network is open, each listing M, each end in a wait; an `unreachable` cleared as the hub's `network` rises
keeps the wait with `on` `network:<x>` and the same `clock-from`; a condition raised 30 s after the failing check
turns it into a wait within the settle, and none within 90 s is held as the delivery's failure; a wait judged
again failing with no cause open ends `own-failure`; the keeper silent waits `on`
`conditions-unread` and is judged when it answers; the keeper's own module failing is its failure with no read;
the module turning healthy with the cause open ends `healthy`; a newer want ends `replaced` and its ask; a restart
of the assigner judges each wait again; past the bound the ask, Go on ending `go-on`, Count as failed ending
`failed`, an unanswered ask raised again; a `rewritten` naming a moved module fails at once; M's own `network`
moves no want to M; `assigner_release` with each `how`, each in the hand-act log; the finding
`delivery-waits-outside` written as a warning that needs nothing and cleared at the end, and no `delivery-waits`
for it. Whole (watchman): a machine silent, and one whose own network is open, while two machines fail toward it,
each list both in `also`. Unit (grants part): the assigner granted `conditions` and the three events, and no read
of the watchman's `findings`.
## The writer's own refusals, in every bundle
- §707 **`finding-refused` is the one kind every bundle's writer owns, within its own bundle's key part.** (§383,
§384, §437, §461, §580; design 73 knowledge §1, §1a) §580 gives each finding kind to one bundle. One kind is the
writer's own: mesh-sdk's finding writer refuses a key it cannot compose (a scope outside the seat
`mesh-conditions`' set, an empty id, a kind or `ref` holding a dot, as design 73 knowledge §1 has it) and writes in
its stead, in the observer's own state `findings`, the finding of kind `finding-refused` (design 73 knowledge §1a),
keyed `module.<observer>.<bundle>.<asked-key-escaped>.finding-refused`, `<bundle>` the bundle's artifact `name` in
the manifest's `build`, and the asked key escaped as a key's name is (§73). A module with one bundle has that
bundle's name there too, so the form has no exception. Every bundle's writer owns that kind within its own key
part only: it writes and clears only `finding-refused` keys of its own bundle. `findings-stated` (§384, §437)
gains `bundle`, of the same form, beside `kinds`; a statement of a bundle, with `kinds` or without, covers the
`finding-refused` keys of that bundle and never another's, and the keeper clears from it only the
`finding-refused` conditions of that bundle it does not name. Every bundle of a module writes the one state
`findings` under the module's one account, so the bus grant cannot tell bundles apart: mesh-sdk's writer, made
with its bundle's name, is what keeps each to its own key part. Why: a refusal is that bundle's own fault, so no
other bundle's statement may clear it (the review of design 73, HE-W2R2-2; review round 1 of batch 8). How it is
checked: unit (writer, both languages), a refused key written as `finding-refused` under its bundle's key part,
escaped; a statement of bundle A leaves bundle B's `finding-refused` key; a writer refusing to write or clear
another bundle's `finding-refused`; unit (contracts), `findings-stated`'s `bundle` read; whole (keeper), two
bundles' statements on one node each keep the other's `finding-refused` condition open.
@@ -0,0 +1,63 @@
---
layer: to-be
status: in-progress
design: 47
milestone: G
updated: 2026-11-11
decisions:
- "ADR 0667"
---
# 47, milestone G — the lead's answers to develop's questions
The operator, 2026-11-11 about 21:30 CET: a develop question is tested against [the principles](../../../00-META/principles.md)
and answered by the lead in one line, without a design batch or a review round for a detail. Each answer here is one line,
names the principle that settles it, and is cited as "design 47 G A-n".
- **A-1** (§686, §640, §687, §689; principle 7, principle 3) `views.FindingBody`'s accessors follow Go's idiom, `Kind()` and
`SetKind(v)` per field; the subject is one pair, `Subject()` and `SetSubject(...)`, with its fields as plain values in the
contract struct's order; the writer is given the generated contract's constructors for `finding-cleared`, `findings-stated`
and `findings-asked` when it is made, never plain maps, so a contract mismatch fails at compile time; `Observed.Findings`
and `Pending` hold `FindingBody` values.
- **A-2** (§655; principle 7, the rule that code shared between modules lives in mesh-sdk) `nats-tools/internal/busarchive`
moves whole with `bussnap` into mesh-sdk as its own package `go/busarchive`, its tests with it; every other importer
(verify, the nightly dump) imports it from there, and no copy stays in mesh-catalog.
- **A-3** (§686, §640, §687; principle 7; replaces A-1) The generated contract types stay as they are, plain structs whose
fields every importer already reads; nothing is generated for the writer and no field is renamed. mesh-sdk's writer is
generic over the contract's body types (`Writer[F, C, S, A any]`, one type parameter per body) and works on their wire
form: it marshals a body, reads and sets `kind`, `scope`, `id`, `subject`, `at` and `since` by their contract names,
and runs `views.CheckFinding` on that form. A body whose wire form lacks a field the contract names fails loudly at its
first write (principle 3) and in the writer's unit test, which runs against the real generated types of
`mesh-conditions`.
- **A-4** (§556; principle 7, and who may do what is no question) The grants part grants a reader of a stream read whole
every subject an ordered consumer of that stream uses: its creation, its next message, its info and the deletion of
its own consumer.
- **A-5** (§614, D-5; principle 7) The branch follower of §614 (registrations, the gate's `source`, adopt and drop of
views, entries by fingerprint kept asked, answered or not found) is built once, in `meshcatalogclient`, and every
part named in §614 uses it; none builds its own.
- **A-6** (§693; principle 7) The grants part keeps reading the assigner's `wants` view and consumes no `wanted`: a want
the assigner removes leaves that view, and the grants part composes no account for it. The `removed` field of §693 is
added to the seat `mesh-wants` for its other readers.
- **A-7** (GR10, §276, §266, §269; principles 1 and 7) The grants part holds the entries of a revision whose accounts its
new version has not yet composed; it keeps the hold in its own state on the bus; `clock-from` is the start of its new
version's first pass, which it knows itself, so it hears no `build.ended`; the bound is §266's granting bound of 10
minutes, a constant of the part.
- **A-8** (§613; principle 7) The template state takes the local name; the gate opens each old section once at its start
by the section's bus name, its own data, and copies a key only when the template lacks that key. No clock or
sequence is compared. Once every key is copied the old section is left to its retirement (§613).
- **A-9** (CT15, §476, §493, §530; principle 8) The `bodies` types are named `TakeInTaken`, `TakeInPending`,
`TakeInMerge`, `TakeInMember` and `TakeInEntry`, as built in mesh-delivery f38e45fd..1c09de8d.
- **A-10** (§276, §498; principles 1 and 7, and who may do what is no question) A holder says a seat event through one
mesh-sdk call, `Conn.EmitSeat(seat, event, body)`, publishing on `mesh.seat.<seat>.event.<event>`; the grants part
grants every holder publish of its held seats' event subjects.
- **A-11** (GR10; principle 7) A wait's `version` is the holder's own running fingerprint, as the indexer names it.
- **A-12** (GR10, §276; principle 4) `grants_release` ends the granting wait: the held entries go on, the wait is said
ended with `how` `released`, and no `acting-part-late` is raised for it.
- **A-13** (§461, §439, §383; principle 7) mesh-sdk's writer forms its four subjects itself, in §383's form
`mesh.stream.<module>.event.<event>.<node>`, from its module and node, through one function
`views.FindingSubjects(module, node)`; a module passes no subjects.
- **A-14** (§580; principles 7 and 8) A finding that told several findings of one kind on one id apart by a `ref` puts that
part into its id (`<id>.<ref>`, each escaped as §73 escapes a name); a kind stays a fixed word of its bundle's list. The
key's scope and id and the subject's scope and id are set equal, as before.
- **A-15** (§614; principle 3) In the branch follower an `entry` the holder refuses is `not-found`; a transport error leaves
it `asked` and is asked again; each part writes `entry-not-found` from the follower's changes. As built in mesh-delivery
ab616fa6.
@@ -170,7 +170,8 @@ names go, since every new acting part needed code changes elsewhere (research 08
| composing | the assigner, holding a node's other wants until its new node-engine runs there (*Composing waits per node*) | `assigner_waits` | `assigner_release` |
| checking | the check's first tier | `checker_first_tier` | its ask-again (*The check on the change's own acting parts*) |
| delivery of a dependency (kinds 2, 4 and 6), from G's delivery | the assigner, holding a dependent's new version until `version-delivered` of its dependency's (§376) | `assigner_waits` | `assigner_release` (want it now), and `assigner_delivered_again` |
| pipeline, from G's delivery | the runner, holding the pipelines its new version is to run until it runs healthy | `runner_waits` | `runner_release` (run them with the running runner) |
| delivery on an outside cause, from G's delivery (§706) | the assigner, holding a moved module's failing check on a machine whose network names an outside cause | `assigner_waits` | `assigner_release` with `how` `go-on`, `failed` or `rejudge` |
| pipeline, from G's delivery | the runner, holding the pipelines its new version is to run until it runs healthy | `runner_waits` | `runner_release` (run them with the running runner) |
Each release writes the hand-act log of the seat `mesh-hand-acts`, with who released and why.
- §277 **How it is checked.** Whole (assigner): a fixture seat declaring a rule, with a fixture holder, gets its edges with
+2
View File
@@ -102,5 +102,7 @@ The part is eighteen files, each read whole, its design lines numbered across th
- [G-16-develop-answers-sixth](G-16-develop-answers-sixth.md): develop's sixth batch: the ledger's upkeep calls, the builder's publishes again and its read of a module's builds, one event of a node's capabilities, the object stores' caps, the gate's merge path from G's delivery, and the readers of a module's manifest (§587 to §594).
- [G-17-develop-answers-seventh](G-17-develop-answers-seventh.md): develop's seventh batch: the operator's answers of 2026-11-11 15:14 to 15:42 CET (callers by class, the five parts' findings, the forge and image registry's other entries, the gate's kept data), how every part reads the catalog half per watched branch, and the refreshed build maps' questions (§610 to §676).
- [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).
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).
+1
View File
@@ -47,6 +47,7 @@ every commit cites the design lines it builds: playbook 07's step 0b, held by it
| Question | Read |
|---|---|
| What do we test every question against? | [`00-META/principles.md`](00-META/principles.md) — the short, living list of principles |
| What does this word mean? | [`00-META/glossary.md`](00-META/glossary.md) |
| How do I do X in this repo? | [`00-META/process/`](00-META/process/) — the playbook index is in `00-overview.md` |
| What was decided, and why? | the knowledge base, through the mesh MCP server: `knowledge-base.ask` with the question in plain words, `knowledge-base.get` with a record's number (`reasoning: true` for the why), `knowledge-base.holds` with a topic of the reading order ([`02-DECISIONS/README.md`](02-DECISIONS/README.md)) |