Merge pull request 'Design 47 milestone G: develop answers batch 5 (G-15 §560-§586), the operator's answers of 2026-11-11 afternoon' (#551) from design/47-G-develop-answers-5 into main
This commit was merged in pull request #551.
This commit is contained in:
+1
-1
@@ -978,7 +978,7 @@ becomes a message). **Decided by** ADR 0227, 0231, 0240, 0252, 0283, 0564, 0668.
|
|||||||
takes a restore point of a module's kept data on the live bus before the module moves across a `form` change, sets
|
takes a restore point of a module's kept data on the live bus before the module moves across a `form` change, sets
|
||||||
the live data aside and restores the point at a revert, and lists and removes restore points; the bus module and
|
the live data aside and restores the point at a revert, and lists and removes restore points; the bus module and
|
||||||
the snapshot account restore nothing into the live bus, and the backup holder only stores copies (design 47 G §554).
|
the snapshot account restore nothing into the live bus, and the backup holder only stores copies (design 47 G §554).
|
||||||
**aside** — live kept data a restore set aside, removed only by the operator's `discard-aside`.
|
**aside** — live kept data a restore set aside, removed only by the hand tool `recovery_discard_aside`, which the operator and sessions call.
|
||||||
*Not:* ~~restorer~~, ~~restore account~~
|
*Not:* ~~restorer~~, ~~restore account~~
|
||||||
- **disk readings** — the size of each data item a node's modules declare, measured by its `measure` and kept
|
- **disk readings** — the size of each data item a node's modules declare, measured by its `measure` and kept
|
||||||
with its largest size in seven days by disk-load on that node, in its own state, one key
|
with its largest size in seven days by disk-load on that node, in its own state, one key
|
||||||
|
|||||||
@@ -1340,7 +1340,8 @@ and `delivered` events.
|
|||||||
- **A module may ship its own Dockerfile.** A build module of its own builds the module's `image` artifact from it, rootless, with no root and no container runtime socket on the build node; a pull request's image is built and thrown away, and only a merged trunk commit's image reaches the registry, by digest. From R4g that module is the only part that builds an image, and build-agent builds none (ADR 0487 §7, ADR 0524 §5); the other builds
|
- **A module may ship its own Dockerfile.** A build module of its own builds the module's `image` artifact from it, rootless, with no root and no container runtime socket on the build node; a pull request's image is built and thrown away, and only a merged trunk commit's image reaches the registry, by digest. From R4g that module is the only part that builds an image, and build-agent builds none (ADR 0487 §7, ADR 0524 §5); the other builds
|
||||||
are Go and Node programs, which their build modules build.
|
are Go and Node programs, which their build modules build.
|
||||||
- **Every dependency comes by the version its lock file names**, checked against its checksum: the mesh's own
|
- **Every dependency comes by the version its lock file names**, checked against its checksum: the mesh's own
|
||||||
code from the mesh's forge, its own packages from its package registry, any other from its public source.
|
code from the mesh's forge, its own packages from its package registry, any other from its public source; a mesh
|
||||||
|
package's entry is the build's to write, by the version the planner read (ADR 0573 §2; design 47 G §571).
|
||||||
- **A build module fetches from the forge over SSH with a key of its own**, as its own account, under a forge
|
- **A build module fetches from the forge over SSH with a key of its own**, as its own account, under a forge
|
||||||
account for that module that reads the mesh's repositories and pushes nothing.
|
account for that module that reads the mesh's repositories and pushes nothing.
|
||||||
- **A build's reuse key** holds the installed toolchain's version and the build module's recipe version in place
|
- **A build's reuse key** holds the installed toolchain's version and the build module's recipe version in place
|
||||||
|
|||||||
@@ -88,7 +88,8 @@ check and deliver milestone G itself (ADR 0667 §2); each of them says so in a l
|
|||||||
verb `branch` (its head, and whether a rule refuses a direct push and admits only merges), and refuse a watched branch
|
verb `branch` (its head, and whether a rule refuses a direct push and admits only merges), and refuse a watched branch
|
||||||
the forge does not protect, naming it (ADR 0666 §3).
|
the forge does not protect, naming it (ADR 0666 §3).
|
||||||
- §6 **The foundation parts are the manifest validator's list.** The manifest validator's list (ADR 0619 §3) holds
|
- §6 **The foundation parts are the manifest validator's list.** The manifest validator's list (ADR 0619 §3) holds
|
||||||
exactly the foundation parts, ADR 0619 §1's and the runner, which joins them (ADR 0666 §4); the checker leaves the
|
exactly the foundation parts, ADR 0619 §1's, the runner, which joins them (ADR 0666 §4), and the forge and image
|
||||||
|
registry modules (§584); the checker leaves the
|
||||||
list when it is removed (*How milestone G itself is checked and delivered*). A registration holds no foundation
|
list when it is removed (*How milestone G itself is checked and delivered*). A registration holds no foundation
|
||||||
value. How it is checked: a unit test of the manifest validator refuses a template in the manifest of every part on
|
value. How it is checked: a unit test of the manifest validator refuses a template in the manifest of every part on
|
||||||
its list, the runner's included, and judges every other part's manifest as any part's.
|
its list, the runner's included, and judges every other part's manifest as any part's.
|
||||||
@@ -366,9 +367,9 @@ check and deliver milestone G itself (ADR 0667 §2); each of them says so in a l
|
|||||||
they are a chain (`mesh-grants:program`, then `node-tools:runtime`, then `mesh-grants:tools`).
|
they are a chain (`mesh-grants:program`, then `node-tools:runtime`, then `mesh-grants:tools`).
|
||||||
- §48 **Removal runs the other way.** When something goes away the order is reversed: a seat moved to a new holder has its
|
- §48 **Removal runs the other way.** When something goes away the order is reversed: a seat moved to a new holder has its
|
||||||
old holder released before the new one claims (ADR 0666 §14).
|
old holder released before the new one claims (ADR 0666 §14).
|
||||||
- §49 **The edges alone order.** The build and the delivery order by these edges alone; a cycle of delivery edges (kinds 2,
|
- §49 **The edges alone order.** (§569) The build and the delivery order by these edges alone; a cycle of delivery edges
|
||||||
4, 5, 6) is delivered as one step, and a cycle of build edges (kinds 1 and 3) is refused, naming every artifact on it
|
(kinds 2, 4, 5, 6) alone is delivered as one step, and a cycle with any build edge (kind 1 or 3), whatever its other
|
||||||
(ADR 0666 §14; research 086, R17). The cycle rule is the indexer's, in the catalog graph it keeps, so the checking
|
edges, is refused, naming every artifact on it (ADR 0666 §14; research 086, R17). The cycle rule is the indexer's, in the catalog graph it keeps, so the checking
|
||||||
program's cycle rule goes with the checker.
|
program's cycle rule goes with the checker.
|
||||||
- §50 **A format's reader first.** A format a running reader cannot read is preceded by its reader, an edge of kind 4 on
|
- §50 **A format's reader first.** A format a running reader cannot read is preceded by its reader, an edge of kind 4 on
|
||||||
every watched branch (ADR 0666 §14): the indexer's manifest validator for a new field of a seat definition or a
|
every watched branch (ADR 0666 §14): the indexer's manifest validator for a new field of a seat definition or a
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ design: 47
|
|||||||
milestone: G
|
milestone: G
|
||||||
updated: 2026-11-11
|
updated: 2026-11-11
|
||||||
decisions:
|
decisions:
|
||||||
|
- "ADR 0500"
|
||||||
|
- "ADR 0573"
|
||||||
- "ADR 0672"
|
- "ADR 0672"
|
||||||
- "ADR 0667"
|
- "ADR 0667"
|
||||||
- "ADR 0666"
|
- "ADR 0666"
|
||||||
@@ -64,8 +66,8 @@ that round are written into the lines they name, here. Questions that an earlier
|
|||||||
`node-backup` on its node as every item is (ADR 0404), which stores the copy and nothing else. When
|
`node-backup` on its node as every item is (ADR 0404), which stores the copy and nothing else. When
|
||||||
`restore-kept` answers `missing`, the node agent calls it again with `from-backup: yes`: the recovery module asks
|
`restore-kept` answers `missing`, the node agent calls it again with `from-backup: yes`: the recovery module asks
|
||||||
the seat `node-backup`'s `restore` of its item for that directory, which brings it back beside its path as that
|
the seat `node-backup`'s `restore` of its item for that directory, which brings it back beside its path as that
|
||||||
verb always does, takes the point from there and restores it; when no repository snapshot holds it, `restored`
|
verb always does, takes the point from there and restores it once its digest is checked (§567); when no
|
||||||
says `failed` with `restore point missing`, and §300 holds the revert.
|
repository snapshot holds it, `restored` says `failed` with `restore point missing`, and §300 holds the revert.
|
||||||
- **The aside, and a restore that fails.** `restore-kept` sets the live kept data aside by taking a stream snapshot
|
- **The aside, and a restore that fails.** `restore-kept` sets the live kept data aside by taking a stream snapshot
|
||||||
of each of its bus objects into `aside/<module>/<kept>/<at>` in the same directory, reads the aside back to check it (`at` the UTC time written
|
of each of its bus objects into `aside/<module>/<kept>/<at>` in the same directory, reads the aside back to check it (`at` the UTC time written
|
||||||
`20261111T121200Z`, with `-2`, `-3` and on added when that name exists), only then removes the live objects, which needs no person's warrant, the data staying in the aside (the operator,
|
`20261111T121200Z`, with `-2`, `-3` and on added when that name exists), only then removes the live objects, which needs no person's warrant, the data staying in the aside (the operator,
|
||||||
@@ -99,7 +101,7 @@ that round are written into the lines they name, here. Questions that an earlier
|
|||||||
(recovery module), `kept-points` lists a point and an aside with their sizes, an aside is gone after
|
(recovery module), `kept-points` lists a point and an aside with their sizes, an aside is gone after
|
||||||
`recovery_discard_aside`, and a restart lists the same.
|
`recovery_discard_aside`, and a restart lists the same.
|
||||||
- §523 **A seat event whose subject has parts.** A seat definition's `subject` with `<part>` tokens (§397), such as
|
- §523 **A seat event whose subject has parts.** A seat definition's `subject` with `<part>` tokens (§397), such as
|
||||||
`mesh-recovery`'s `ended.<module>.<kept>` and `node-backup`'s `item-started.<node>.<module>` (§554), is said on
|
`mesh-recovery`'s `ended.<module>.<kept>` and `node-backup`'s `item-started.<node>.<module>.<item>` (§554), is said on
|
||||||
`mesh.seat.<seat>.event.` followed by the subject, each part filled in the definition's order: the seat
|
`mesh.seat.<seat>.event.` followed by the subject, each part filled in the definition's order: the seat
|
||||||
generator's subject function for the event takes each part as a string in that order and fills each as one token,
|
generator's subject function for the event takes each part as a string in that order and fills each as one token,
|
||||||
escaped as a key's name is (§73), refusing an empty part, `.` and `..`. A reader hears one module's events by the subject with
|
escaped as a key's name is (§73), refusing an empty part, `.` and `..`. A reader hears one module's events by the subject with
|
||||||
@@ -179,9 +181,13 @@ that round are written into the lines they name, here. Questions that an earlier
|
|||||||
with no `parts` (from an assigner of before G, or for a node whose record does not state `want-parts`, §525) is
|
with no `parts` (from an assigner of before G, or for a node whose record does not state `want-parts`, §525) is
|
||||||
applied as today, its resources fetched by their sources and checked by their own digests. A want with `parts` is
|
applied as today, its resources fetched by their sources and checked by their own digests. A want with `parts` is
|
||||||
applied only when the digest of every resource it fetched is among the values of the want's `parts`, and
|
applied only when the digest of every resource it fetched is among the values of the want's `parts`, and
|
||||||
every value of `parts` is the digest of a resource it fetched; otherwise it applies nothing of that module and its
|
every value of `parts` is the digest of a resource it fetched; otherwise it applies nothing of that module, its
|
||||||
have says the phase `parts-differ`, naming the digest. `parts` stays keyed by `<module>:<artifact>` for people and
|
have says the phase `held` (one of the seat's phases, which gains none) with its detail opening `parts-differ:` and
|
||||||
the delivery record. This completes §379. Why: the digest is what is fetched and checked (develop question H-8). How
|
naming each digest that differs, and it says `wait-held` with the reason `parts-differ` (§541). `parts`
|
||||||
|
stays keyed by `<module>:<artifact>` for people and
|
||||||
|
the delivery record. This completes §379. Why: the digest is what is fetched and checked (develop question H-8); a
|
||||||
|
hold is the phase `held` with its reason, as every hold of §300, §421 and §499 is, so the seat's phases stay as they
|
||||||
|
are (develop question of 2026-11-11 on H-8's phase, batch 5). How
|
||||||
it is checked: unit (node-engine), a want whose parts and fetched digests agree applies, and one with a fetched
|
it is checked: unit (node-engine), a want whose parts and fetched digests agree applies, and one with a fetched
|
||||||
digest outside `parts` or a part not fetched applies nothing, naming it; whole (node-engine of G), a want written by
|
digest outside `parts` or a part not fetched applies nothing, naming it; whole (node-engine of G), a want written by
|
||||||
an assigner of before G is applied.
|
an assigner of before G is applied.
|
||||||
@@ -355,9 +361,17 @@ that round are written into the lines they name, here. Questions that an earlier
|
|||||||
- §528 **The checker built from G's heads asks no group build.** From G's delivery the pipeline is the check and the
|
- §528 **The checker built from G's heads asks no group build.** From G's delivery the pipeline is the check and the
|
||||||
run on request the try (§66), so the checker built from G's heads makes no group check: its group build through
|
run on request the try (§66), so the checker built from G's heads makes no group check: its group build through
|
||||||
tagged versions (its check's group path, `judge.go`'s, and `tagwanted.go`) goes with `tag-wanted` (§373), nothing replaces it in
|
tagged versions (its check's group path, `judge.go`'s, and `tagwanted.go`) goes with `tag-wanted` (§373), nothing replaces it in
|
||||||
the checker, and a group's builds against its package members' digests are the runner's (§373, §465). Until G's
|
the checker, and a group's builds against its package members' digests are the runner's (§373, §465). The
|
||||||
|
checker's old Node form goes with it: it no longer packs a group member's package for a Node fetch (ADR 0500 §5),
|
||||||
|
for any group, since a group's builds against its members' heads are the runner's (ADR 0573 §4). The checker's
|
||||||
|
manifest of G's heads consumes neither package registry's `published` and its asks stream carries no `tag-wanted`;
|
||||||
|
its `go.mod` requires nothing that no code of it imports; and the checker's seat definition in mesh-contracts
|
||||||
|
defines no `tag-wanted` holder event, which goes as §321 retires `tag-wanted`. Until G's
|
||||||
delivery the running checker makes G's own check with main's code (ADR 0667 §2). Why: §66 and §373 (develop
|
delivery the running checker makes G's own check with main's code (ADR 0667 §2). Why: §66 and §373 (develop
|
||||||
question CK10). How it is checked: the code review finds no group build in the checker of G's heads.
|
questions CK10 and the checker developer's three after it, batch 5). How it is checked: the code review finds no
|
||||||
|
group build and no Node packing in the checker of G's heads; unit (manifest validator), the checker's manifest of
|
||||||
|
G's heads accepted without the two `consumes`; unit (mesh-contracts), the checker's seat definition holds no
|
||||||
|
`tag-wanted`.
|
||||||
- §534 **The wait's `step` in the runner's body.** The runner's wait body keeps `step` as the pipeline step a wait inside
|
- §534 **The wait's `step` in the runner's body.** The runner's wait body keeps `step` as the pipeline step a wait inside
|
||||||
a pipeline is in (`lint`, `unit`, `integration`, `composition`, `review`, `approval`), and gains the value
|
a pipeline is in (`lint`, `unit`, `integration`, `composition`, `review`, `approval`), and gains the value
|
||||||
`pipeline`, the acting step of §203, for a wait of the entries the runner holds for its new version (§266,
|
`pipeline`, the acting step of §203, for a wait of the entries the runner holds for its new version (§266,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ design: 47
|
|||||||
milestone: G
|
milestone: G
|
||||||
updated: 2026-11-11
|
updated: 2026-11-11
|
||||||
decisions:
|
decisions:
|
||||||
|
- "ADR 0259"
|
||||||
- "ADR 0672"
|
- "ADR 0672"
|
||||||
- "ADR 0436"
|
- "ADR 0436"
|
||||||
- "ADR 0667"
|
- "ADR 0667"
|
||||||
@@ -51,25 +52,22 @@ are written into the lines of G-12 they name.*
|
|||||||
- **Its seat, module and node.** The seat `mesh-recovery`, held once for the mesh, is defined in mesh-contracts
|
- **Its seat, module and node.** The seat `mesh-recovery`, held once for the mesh, is defined in mesh-contracts
|
||||||
beside `mesh-broker`, and the module `mesh-recovery`, in mesh-catalog, claims it; its glossary word is the
|
beside `mesh-broker`, and the module `mesh-recovery`, in mesh-catalog, claims it; its glossary word is the
|
||||||
*recovery module*. It runs on the node of the holder of `mesh-broker`, read from the catalog half and the seat
|
*recovery module*. It runs on the node of the holder of `mesh-broker`, read from the catalog half and the seat
|
||||||
`mesh-module-assigner`'s placements, never a fixed name: G's seed writes its placement there, and the
|
`mesh-module-assigner`'s placements, never a fixed name: G's seed writes its placement there. It moves as any
|
||||||
placement verb refuses to move it while `kept-points` lists a point younger than 90 days, naming them, so its
|
module that holds data, its points and asides holding no move (§562). Its data directory, its manifest's `data`
|
||||||
points and their copies in that node's repository stay together. Its data directory, its manifest's `data` item
|
item `points`, is capped by its setting `points-cap` and measured by the disk readings (ADR 0571 §5): past its fill
|
||||||
`points`, is capped at 10 GiB and measured by the disk readings (ADR 0571 §5): past 80 % it writes the finding
|
mark it writes the finding `points-filling` (§561), and an act that would pass the cap ends `failed`, naming it,
|
||||||
`points-filling`, and a `snapshot-kept` that would pass the cap ends `failed`, naming it, which holds the move as a
|
before it removes anything; a `snapshot-kept` that ends so holds the move as a failed backup does (§296, §564). Its `findings` state and finding stream are declared as §529's other parts declare
|
||||||
failed backup does (§296). Its `findings` state and finding stream are declared as §529's other parts declare
|
|
||||||
them, so it waits on the bus module for them and is no foundation part (ADR 0619 §1).
|
them, so it waits on the bus module for them and is no foundation part (ADR 0619 §1).
|
||||||
- **Its verbs answer at once; the result is the event.** `snapshot-kept` and `restore-kept` answer `accepted` with
|
- **Its verbs answer at once; the result is the event.** `snapshot-kept` and `restore-kept` answer `accepted` with
|
||||||
the act's `act` id, `busy` with the act that runs (it runs one act at a time and keeps no queue), or `error`, and
|
the act's `act` id, `busy` with the act that runs (it runs one act at a time and keeps no queue), or `error`, and
|
||||||
nothing more; the point comes on `ended`, the restore on `restored`. A caller told `busy` asks again when it hears
|
nothing more; the point comes on `ended`, the restore on `restored`. A caller told `busy` asks again when it hears
|
||||||
that act's event. The module writes each accepted act in its directory before it answers; at its start an act
|
the ending event of the act it was named (§560). The module writes each accepted act in its directory before it answers; at its start an act
|
||||||
accepted and not ended is ended `failed` with `stopped`, so its caller asks again.
|
accepted and not ended is ended `failed` with `stopped`, so its caller asks again.
|
||||||
- **Its events.** On `mesh.seat.mesh-recovery.event.` and kept last per subject, 90 days (§396): `ended.<module>.<kept>`
|
- **Its events.** On `mesh.seat.mesh-recovery.event.` and kept last per subject, 90 days (§396): `ended`,
|
||||||
and `restored.<module>.<kept>`, each carrying `act`, `module`, `kept`, `form`, `fingerprint`, `snapshot` and
|
`restore-started`, `restored`, `set-aside`, `aside-discarded` and `point-removed`, each with the parts
|
||||||
`outcome` (`done` or `failed`, with `error`), `ended` also the point whole; `restore-started.<module>.<kept>` when a
|
`<module>.<kept>`, and `expiry-ended`, their fields as §560 gives them. The node agent wakes only on the ending
|
||||||
restore begins; `set-aside.<module>.<kept>` and `aside-discarded.<module>.<kept>` with the aside's `id` and
|
event of its own act, and its wait for `ended` or `restored` is bounded at 90 minutes from its first ask (§405,
|
||||||
`size`; and `point-removed.<module>.<kept>` (§551). The node agent wakes only on the event whose `form` and
|
§560), past which its have says the wait and the watchman's `delivery-waits` raises it.
|
||||||
`fingerprint` are its ask's. Its wait for `ended` or `restored` is bounded at 90 minutes (§405), past which its have
|
|
||||||
says the wait and the watchman's `delivery-waits` raises it.
|
|
||||||
- **Who calls it.** `snapshot-kept` and `restore-kept` are called by a node-engine holder (`seat:node-engine`): the
|
- **Who calls it.** `snapshot-kept` and `restore-kept` are called by a node-engine holder (`seat:node-engine`): the
|
||||||
recovery module takes a call only from an account the bus proves to be a node-engine's, and the identity of who
|
recovery module takes a call only from an account the bus proves to be a node-engine's, and the identity of who
|
||||||
asked is the check (the operator, 13:06 CET), every act logged; no want is read for it, since the operator,
|
asked is the check (the operator, 13:06 CET), every act logged; no want is read for it, since the operator,
|
||||||
@@ -85,16 +83,24 @@ are written into the lines of G-12 they name.*
|
|||||||
- **The operator's hand tools.** `recovery_take` (take a point of one module and kept data now), `recovery_restore`
|
- **The operator's hand tools.** `recovery_take` (take a point of one module and kept data now), `recovery_restore`
|
||||||
(restore one point) and `recovery_retry` (ask again the last failed act of a module and kept data), each of class
|
(restore one point) and `recovery_retry` (ask again the last failed act of a module and kept data), each of class
|
||||||
`act`, callers `operator` and `sessions` (§391), written in the hand-act log; they are checked by identity, as above.
|
`act`, callers `operator` and `sessions` (§391), written in the hand-act log; they are checked by identity, as above.
|
||||||
- **Its account.** Composed by the grants part from the seat's definition and the manifest: the bus's stream
|
§566 adds `recovery_restore_aside` and `recovery_cancel`.
|
||||||
|
- **Its account.** The operator, 2026-11-11 about 14:15 CET at lead-47's terminal (the knowledge base's review of
|
||||||
|
ADR 0672, R3): the recovery module is one process with a bus account of its own (ADR 0436 §1, as ADR 0626 §1 has
|
||||||
|
the bus module's keeper), which holds the seat `mesh-recovery` and answers its verbs itself; each verb is one its
|
||||||
|
caller names (`by-caller`, ADR 0259 §3), so the bus proves who calls: a node-engine's account for `snapshot-kept`
|
||||||
|
and `restore-kept`, and the tool runner's account, which the sessions and the operator reach the bus as, for its
|
||||||
|
hand acts. Its tools bundle, carried by the tool runner, calls those verbs and holds no grant of its own. ADR 0672
|
||||||
|
§4 records that this changes ADR 0436 §3 and §5 for this process alone. The account is composed by the grants part
|
||||||
|
from the seat's definition and the process's `bus` declaration: the bus's stream
|
||||||
snapshot and restore subjects with their chunk subjects, a stream's deletion and a durable consumer's creation,
|
snapshot and restore subjects with their chunk subjects, a stream's deletion and a durable consumer's creation,
|
||||||
only for the bus names of a module's kept data; the subjects its seat says and its hand-act log write; its
|
only for the bus names of a module's kept data; the subjects its seat says and its hand-act log write; its
|
||||||
consumers of `node-backup`'s `item-started` and `item-ended`, each with the ordered
|
consumers of `node-backup`'s `item-started` and `item-ended`, filtered to those two events, each with the ordered
|
||||||
consumer §556 needs; its calls of `node-backup`'s `restore` as the caller `holder:mesh-recovery@same-node`, which
|
consumer §556 needs, from the process's `consumes`; its calls of `node-backup`'s `restore` as the caller `holder:mesh-recovery@same-node`, which
|
||||||
`node-backup`'s definition names for `restore` and which the backup holder takes only for the recovery module's
|
`node-backup`'s definition names for `restore` and which the backup holder takes only for the recovery module's
|
||||||
own item `points` (the operator, 13:02 CET); and nothing else. The bus names granted are those of every kept data
|
own item `points` (the operator, 13:02 CET); and nothing else. The bus names granted are those of every kept data
|
||||||
of every catalog graph entry the catalog half keeps (§443) and of every entry a restore point names (an old
|
of every catalog graph entry the catalog half keeps (§443) and of every entry a restore point names (an old
|
||||||
section's name before a form change, a template's binding after), read by the grants part through
|
section's name before a form change, a template's binding after), read by the grants part through
|
||||||
`kept-points`; no stream of the mesh's own (`CONTROL`, `NODES`, `EVENTS`, `DEAD_LETTER_NOTICES`, `DEAD_LETTERS`,
|
`kept-points` (§565); no stream of the mesh's own (`CONTROL`, `NODES`, `EVENTS`, `DEAD_LETTER_NOTICES`, `DEAD_LETTERS`,
|
||||||
`PROV_APPLIED`, `CHECKS_READY`, `CHECKS_OTHER`, every `SEAT_` stream and every `KV_` bucket of a seat) is ever
|
`PROV_APPLIED`, `CHECKS_READY`, `CHECKS_OTHER`, every `SEAT_` stream and every `KV_` bucket of a seat) is ever
|
||||||
granted. Restricted streams (ADR 0436) are among the names, as ADR 0672 records.
|
granted. Restricted streams (ADR 0436) are among the names, as ADR 0672 records.
|
||||||
- **Bus names.** The recovery module turns a module and a kept data into bus names from the catalog graph entry of
|
- **Bus names.** The recovery module turns a module and a kept data into bus names from the catalog graph entry of
|
||||||
@@ -105,19 +111,20 @@ are written into the lines of G-12 they name.*
|
|||||||
it, so the server has at most two snapshots at once. No `restore-kept` starts while the dump runs, and no dump of
|
it, so the server has at most two snapshots at once. No `restore-kept` starts while the dump runs, and no dump of
|
||||||
the bus starts while a restore runs: the holder of `node-backup` of G says `item-started.<node>.<module>.<item>`
|
the bus starts while a restore runs: the holder of `node-backup` of G says `item-started.<node>.<module>.<item>`
|
||||||
and `item-ended.<node>.<module>.<item>` for every item, kept last per subject, 7 days, and puts off the bus's item
|
and `item-ended.<node>.<module>.<item>` for every item, kept last per subject, 7 days, and puts off the bus's item
|
||||||
while a `restore-started` of the recovery module has no `restored`; the recovery module learns the bus module and
|
while a `restore-started` of the recovery module has no `restored`, the dump giving way when both start at once
|
||||||
|
(§563); the recovery module learns the bus module and
|
||||||
its node from the seat list's definition of `mesh-broker` and the catalog half's claim of it, never a fixed name.
|
its node from the seat list's definition of `mesh-broker` and the catalog half's claim of it, never a fixed name.
|
||||||
Both read these streams as §556 has it, so a restart mid-dump or mid-restore misses neither. A blocked act waits,
|
Both read these streams as §556 has it, so a restart mid-dump or mid-restore misses neither. A blocked act waits,
|
||||||
neither refused nor failing a want: past 60 minutes the recovery module writes `recovery-waits` and the backup
|
neither refused nor failing a want: past 60 minutes the recovery module writes `recovery-waits` and the backup
|
||||||
holder `backup-waits`, each naming the item or the act it waits on, and `kept-points` lists the act that runs
|
holder `backup-waits`, each naming the item or the act it waits on, and `kept-points` lists the act that runs
|
||||||
with since when and what it waits on. The recovery module consumes the item events that G's backup holder adds,
|
with since when and what it waits on. The recovery module consumes the item events that G's backup holder adds,
|
||||||
an edge of kind 6 from that holder to it, so a backup holder of before G, which says none, is never relied on.
|
an edge of kind 6 from that holder to it, so a backup holder of before G, which says none, is never relied on.
|
||||||
- **Its health.** Its declared health check calls `kept-points`, and fails while any aside's record ends at
|
- **Its health.** Its declared health check calls `kept-points`, and fails only while an aside's record ends at
|
||||||
`removed` (§516), when it also writes the finding `aside-unrestored` naming the module, the kept data and the
|
`removed` (§516) and no running act holds it, so a restore under way never fails it; it then also writes the
|
||||||
aside's `id`.
|
finding `aside-unrestored` (§561), which `recovery_restore_aside` (§566) clears.
|
||||||
- **Its order.** The node-engine's `invokes` of its verbs gives the edge of kind 6 from the recovery module to the
|
- **Its order.** The node-engine's `invokes` of its verbs gives the edge of kind 6 from the recovery module to the
|
||||||
node-engine, so §298's first edge reads "the new version of the recovery module" (§555). At a revert of G the
|
node-engine, so §298's first edge reads "the new version of the recovery module" (§555). At a revert of G the
|
||||||
edge runs backward (ADR 0656 §4): the node-engine goes back only after every module it restores there said
|
edge runs backward, as the order does when something goes away (ADR 0666 §14): the node-engine goes back only after every module it restores there said
|
||||||
`restored` and runs (§298), and the recovery module, new in G, goes only after the node-engine, so it stays while
|
`restored` and runs (§298), and the recovery module, new in G, goes only after the node-engine, so it stays while
|
||||||
any restore runs; its data item stays on its node, with its copies.
|
any restore runs; its data item stays on its node, with its copies.
|
||||||
- **Its tools** are named `recovery_`.
|
- **Its tools** are named `recovery_`.
|
||||||
@@ -172,7 +179,7 @@ are written into the lines of G-12 they name.*
|
|||||||
- §558 **A field of a served verb's answer is an edge of kind 6.** Kind 6 (§374) orders a module after a version that
|
- §558 **A field of a served verb's answer is an edge of kind 6.** Kind 6 (§374) orders a module after a version that
|
||||||
serves a verb or a word it uses, and a verb's presence alone says nothing of a field its answer gained, so a
|
serves a verb or a word it uses, and a verb's presence alone says nothing of a field its answer gained, so a
|
||||||
consumer relying on a new field of a served answer could run before the provider's new version and fall back in
|
consumer relying on a new field of a served answer could run before the provider's new version and fall back in
|
||||||
silence (the grants part's first view relies on `binding` in `mesh-broker`'s `list`). An `invokes` entry therefore
|
silence (as the grants part's first view relied on `binding` in `mesh-broker`'s `list` before design 25's §9). An `invokes` entry therefore
|
||||||
takes a long form, `{verb, fields}`: `verb` as today (`seat:<seat>.<verb>`), `fields` the names of its answer's
|
takes a long form, `{verb, fields}`: `verb` as today (`seat:<seat>.<verb>`), `fields` the names of its answer's
|
||||||
fields the consumer relies on. The manifest validator refuses a field the seat's definition does not give that
|
fields the consumer relies on. The manifest validator refuses a field the seat's definition does not give that
|
||||||
verb's answer, naming it. The delivery plan derives the edge of kind 6 from the holders of that seat to the
|
verb's answer, naming it. The delivery plan derives the edge of kind 6 from the holders of that seat to the
|
||||||
@@ -184,14 +191,15 @@ are written into the lines of G-12 they name.*
|
|||||||
form, and the running checker, the indexer and the grants part, which read manifests through it, are rebuilt with
|
form, and the running checker, the indexer and the grants part, which read manifests through it, are rebuilt with
|
||||||
it by the release's publish (kind 1), as for `max-mib`. That publish rebuilds every module importing mesh-sdk's
|
it by the release's publish (kind 1), as for `max-mib`. That publish rebuilds every module importing mesh-sdk's
|
||||||
`catalogue`, the set the release rebuilds already, so the form adds no rebuild. The consumers of G that name fields:
|
`catalogue`, the set the release rebuilds already, so the form adds no rebuild. The consumers of G that name fields:
|
||||||
the grants part, `mesh-broker`'s `list` with `binding`; every reader of `mesh-catalog`'s `revision` through
|
every reader of `mesh-catalog`'s `revision` through
|
||||||
mesh-sdk's client (the bus module, the status view, the condition keeper, the tool runner, the assigner, the grants
|
mesh-sdk's client (the bus module, the status view, the condition keeper, the tool runner, the assigner, the grants
|
||||||
part and the runner), with `none-yet` (§530); the status view, `mesh-catalog`'s `entry` with `manifest-digest`
|
part and the runner), with `none-yet` (§530); the status view, `mesh-catalog`'s `entry` with `manifest-digest`
|
||||||
(§506). The recovery module reads the manifest whole the entry carries (§443), a field of before G. Any other part of G relying on a field G adds to a served answer names it so in G's change, which the
|
(§506). The grants part names none: design 25 *bindings-first-view* §9 composes a binding from the fields `list` answered before G, so it relies on no
|
||||||
|
new field of `list`, and naming `binding` would close the circle of §569. The recovery module reads the manifest whole the entry carries (§443), a field of before G. Any other part of G relying on a field G adds to a served answer names it so in G's change, which the
|
||||||
code review checks. Why: the module graph orders a consumer after what it relies on, and a field is part of the contract
|
code review checks. Why: the module graph orders a consumer after what it relies on, and a field is part of the contract
|
||||||
(lead-47's question from the operator's "the module graph is for this", 2026-11-11). How it is checked: unit
|
(lead-47's question from the operator's "the module graph is for this", 2026-11-11). How it is checked: unit
|
||||||
(manifest validator), a field the definition lacks refused; unit (delivery plan), the grants part ordered after
|
(manifest validator), a field the definition lacks refused; unit (delivery plan), a consumer naming a field
|
||||||
a bus module whose definition gives `binding`, and not before; unit (the release's reader), both forms read.
|
ordered after a holder whose definition gives it, and not before; unit (the release's reader), both forms read.
|
||||||
- §559 **A bundle's finding writer publishes and hears through two runtime calls.** A bundle, in Go or TypeScript,
|
- §559 **A bundle's finding writer publishes and hears through two runtime calls.** A bundle, in Go or TypeScript,
|
||||||
holds no bus connection, so mesh-sdk's finding writer (§461, §503) in a bundle uses the runtime channel's existing
|
holds no bus connection, so mesh-sdk's finding writer (§461, §503) in a bundle uses the runtime channel's existing
|
||||||
calls, each gaining one argument: `mesh/publish` takes `ack: true`, and the tool runner then publishes the event on
|
calls, each gaining one argument: `mesh/publish` takes `ack: true`, and the tool runner then publishes the event on
|
||||||
@@ -206,4 +214,5 @@ are written into the lines of G-12 they name.*
|
|||||||
languages over the one channel a bundle has, as §518 (develop question of 13:08 CET on §461). How it is checked:
|
languages over the one channel a bundle has, as §518 (develop question of 13:08 CET on §461). How it is checked:
|
||||||
unit (tool runner), a publish with `ack` answered with its sequence and a refused one with `{error}`, a `deliver:
|
unit (tool runner), a publish with `ack` answered with its sequence and a refused one with `{error}`, a `deliver:
|
||||||
new` subscription given no message older than it; whole (mesh-sdk, TypeScript and Go bundles), a finding written
|
new` subscription given no message older than it; whole (mesh-sdk, TypeScript and Go bundles), a finding written
|
||||||
and an ask answered through a tool runner of G.
|
and an ask answered through a tool runner of G; unit (mesh-sdk, both languages), the writer fails at once, naming
|
||||||
|
`finding-calls` and the node, against a tool runner that does not state it.
|
||||||
|
|||||||
@@ -0,0 +1,635 @@
|
|||||||
|
---
|
||||||
|
layer: to-be
|
||||||
|
status: in-progress
|
||||||
|
design: 47
|
||||||
|
milestone: G
|
||||||
|
updated: 2026-11-11
|
||||||
|
decisions:
|
||||||
|
- "ADR 0672"
|
||||||
|
- "ADR 0668"
|
||||||
|
- "ADR 0667"
|
||||||
|
- "ADR 0666"
|
||||||
|
- "ADR 0664"
|
||||||
|
- "ADR 0626"
|
||||||
|
- "ADR 0619"
|
||||||
|
- "ADR 0596"
|
||||||
|
- "ADR 0595"
|
||||||
|
- "ADR 0573"
|
||||||
|
- "ADR 0564"
|
||||||
|
- "ADR 0539"
|
||||||
|
- "ADR 0500"
|
||||||
|
- "ADR 0429"
|
||||||
|
- "ADR 0404"
|
||||||
|
- "ADR 0283"
|
||||||
|
- "ADR 0259"
|
||||||
|
- "ADR 0235"
|
||||||
|
---
|
||||||
|
|
||||||
|
# 47, milestone G: develop's fifth batch, and round 3's notes on §516 to §559
|
||||||
|
|
||||||
|
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".
|
||||||
|
|
||||||
|
*§560 to §586 answer develop's fifth batch (lead-47's input of 2026-11-11), the reviewers' round-3 notes on §516 to
|
||||||
|
§559, the knowledge base's review of ADR 0672 (the recovery module), and round 1 of this batch's own review, written
|
||||||
|
into the lines it names. Seven carry the operator's answers of 2026-11-11 at lead-47's terminal, each line saying
|
||||||
|
so: §562 (the module's move), §563 (a put-off dump), §568 (the builder's retry), §570 (refused asks), §575 (a failed
|
||||||
|
build's words), §584 (the forge and image registry in the foundation) and §554's account. The rest are of internal
|
||||||
|
form only. A note that corrects a line of G-12 or G-14 is written in that line; here only what is new.*
|
||||||
|
|
||||||
|
## The recovery module
|
||||||
|
|
||||||
|
- §560 **Every event of the recovery module says its act, and its caller wakes on its own act.** (§554, §516, §551)
|
||||||
|
Every event of the seat `mesh-recovery` carries `act`, the id `snapshot-kept` or `restore-kept` answered with
|
||||||
|
`accepted`, or a hand tool's own act id (§566), and `at`, the UTC time it was said in RFC 3339. Each event's other
|
||||||
|
fields:
|
||||||
|
- `ended.<module>.<kept>`: `module`, `kept`, `form`, `fingerprint`, `snapshot`, `outcome` (`done` or `failed`),
|
||||||
|
`error` when failed, and on `done` the point whole (§516).
|
||||||
|
- `restore-started.<module>.<kept>`: `module`, `kept`, `form`, `fingerprint` and `snapshot`, said before the
|
||||||
|
restore reads the dump's item events and before any aside is taken (§563).
|
||||||
|
- `restored.<module>.<kept>`: `module`, `kept`, `form`, `fingerprint`, `snapshot`, `outcome`, `error`, `aside` and
|
||||||
|
`missing` (§516).
|
||||||
|
- `set-aside.<module>.<kept>` and `aside-discarded.<module>.<kept>`: the aside's `id`, `name` and `size`.
|
||||||
|
- `point-removed.<module>.<kept>` as §551 has it; and `expiry-ended`, a subject without parts, with `removed`, the
|
||||||
|
number of points the run removed, 0 included.
|
||||||
|
- **Every act ends with an event under its `act`.** `snapshot-kept` and `recovery_take` end with `ended`;
|
||||||
|
`restore-kept`, `recovery_restore` and `recovery_restore_aside` (§566) with `restored`; `recovery_aside` with
|
||||||
|
`set-aside`; `recovery_discard_aside` with `aside-discarded`; a run of §551's removal (at the start, once a day,
|
||||||
|
at a `snapshot-kept` or by `recovery_expire_points`) with `expiry-ended`, also when it removes nothing;
|
||||||
|
`recovery_retry` with the ending event of the act it asks again, under an `act` of its own; `recovery_cancel`
|
||||||
|
(§566) with the cancelled act's ending event, `outcome` `failed` and `error` `cancelled`.
|
||||||
|
- **An act a restart cut off** (accepted and written in the directory, never ended, §554) is ended at the module's
|
||||||
|
start, after the start's repair of asides (§516, §564), with its own ending event under its `act`, `outcome`
|
||||||
|
`failed` and `error` `stopped`.
|
||||||
|
- **A restore runs** from its `restore-started` until a `restored` with the same `act`; the backup holder reads it
|
||||||
|
so (§554, §563).
|
||||||
|
- **The caller wakes on its own act.** The node agent told `accepted` wakes only on an `ended` or a `restored`
|
||||||
|
whose `act` is the one it was given; a `form` and a `fingerprint` alone wake nothing, since a retried act's old
|
||||||
|
`failed` carries the same ones. Told `busy` with the running act's `act`, it wakes on that act's ending event
|
||||||
|
and asks again, and its new answer gives the `act` it waits on next.
|
||||||
|
- **The 90-minute bound** of the node agent's wait (§554) counts from its first ask for that point or restore,
|
||||||
|
every `busy` and every ask again within it. Past it, the node agent's have says the wait and the watchman's
|
||||||
|
`delivery-waits` raises it.
|
||||||
|
- **How the node agent hears and keeps it.** The node-engine's manifest `consumes` `mesh-recovery`'s `ended` and
|
||||||
|
`restored`, read as §556 has it. Before it asks, the node agent writes in its have the want's wait with `ask-at`
|
||||||
|
(its first ask's time); once answered `accepted`, it writes the `act` there too. After a restart it reads that
|
||||||
|
have: an `act` whose ending event the read of §556 already gives is taken as heard, and one not yet ended is
|
||||||
|
waited on, asked nothing again; a wait with no `act` yet is asked again within its bound.
|
||||||
|
- **What the node agent does with each ending.**
|
||||||
|
|
||||||
|
| outcome, `error` | what the node agent does |
|
||||||
|
|---|---|
|
||||||
|
| `done` | goes on with the move or the revert |
|
||||||
|
| `failed`, `stopped` (a restart or a move cut the act off, §562) | asks again, within the same bound |
|
||||||
|
| `failed`, `cancelled` (§566) | asks nothing again; holds the move, the reason `cancelled` with the hand act's `why` |
|
||||||
|
| `failed`, `cap` (§564) | holds the move, the reason the error's own words |
|
||||||
|
| `failed`, `restore point missing` or `restore point damaged` (§516, §567) | holds the revert as §300 has it, the reason the error's own words |
|
||||||
|
| `failed`, any other error | holds the move, the reason the error's own words |
|
||||||
|
|
||||||
|
A hold is the phase `held` with that reason, said as `wait-held` (§541), and ends on a new want or the
|
||||||
|
operator's hand act (`recovery_retry`, then a new ask of the node agent on that act's ending).
|
||||||
|
|
||||||
|
This replaces §554's list of events. Why: an event a caller cannot tie to its own call wakes it on another's
|
||||||
|
failure, and an act whose end is never said holds its caller unseen (round 3, health and events, items 1 and 2;
|
||||||
|
running and testing, item 3). How it is checked: unit (mesh-recovery's contract), each event's fields read; whole
|
||||||
|
(recovery module), a retried act's caller not woken by the first act's `failed`, an expiry run that removes nothing
|
||||||
|
says `expiry-ended` with `removed` 0, an act cut off by a restart ends `failed` with `stopped`; unit (node agent),
|
||||||
|
`busy`, then the other act's ending event, then an ask again within one bound, the bound passed after repeated
|
||||||
|
`busy` answers, and each row of the table; whole (node-engine, recovery module), a node-engine restarted during a
|
||||||
|
restore takes that restore's `restored` and asks nothing again.
|
||||||
|
- §561 **The recovery module's and the backup holder's findings, each with its scope, id and clearing.** (§554) Each
|
||||||
|
is written by mesh-sdk's finding writer (§461) as the key `<scope>.<id>.<kind>` (ADR 0564 §2), each token escaped
|
||||||
|
as a key's name is (§73), and said on the part's finding stream (§383, §529):
|
||||||
|
- `points-filling`: the recovery module's, scope `mesh-recovery`, id the node it runs on. It is written when the
|
||||||
|
directory of its data item `points` passes the fill mark of its cap (§564), which the recovery module measures
|
||||||
|
itself at its start, after each act and after each expiry run, naming the size, the cap and the five largest points and asides. It is cleared when a
|
||||||
|
measure finds it below the mark.
|
||||||
|
- `recovery-waits`: the recovery module's, scope the module whose act waits, id the act's `act`. It is written
|
||||||
|
60 minutes after the act began waiting on the dump of the bus's item (§563), naming the item and since when. It
|
||||||
|
is cleared when the act starts its work, or ends.
|
||||||
|
- `backup-waits`: the backup holder's, scope its node, id the item that waits (`<module>.<item>`, one escaped
|
||||||
|
token). It is written 60 minutes (its setting `put-off-bound`, §557) after the item was put off (§563), naming the restore's `act`. It is cleared
|
||||||
|
when the item starts again.
|
||||||
|
- `aside-unrestored`: the recovery module's, scope the module, id the aside's `id`. It is written at an act's end
|
||||||
|
and at the module's start for each aside whose record ends at `removed` and that no running act holds, which
|
||||||
|
the health check also fails on (§554). It is cleared when that
|
||||||
|
aside's record ends at `restored` or the aside is discarded.
|
||||||
|
|
||||||
|
The recovery module and the backup holder of G are observers on the condition keeper's list of sources (§387,
|
||||||
|
§388), written into it in G's change. Why: a finding no one can clear stays open for ever, and the four findings
|
||||||
|
of §554 named no scope, id or clearing (round 3, health and events, item 4). How it is checked: whole (recovery
|
||||||
|
module, backup holder, the keeper), one whole test writes and then clears each: the points directory filled past
|
||||||
|
the mark, then an aside discarded; an act held by a dump past the bound (a setting, §557), then started; a dump
|
||||||
|
held past it, then started; an aside left at `removed` with no running act, then restored by
|
||||||
|
`recovery_restore_aside`.
|
||||||
|
- §562 **The recovery module moves as any module that holds data; its points and asides hold no move.** (§554) The
|
||||||
|
operator, 2026-11-11 about 14:15 CET at lead-47's terminal: the recovery module may be moved off its node at any
|
||||||
|
time, and the restore points and asides in its directory do not hold the move. A placement that moves it is made as
|
||||||
|
for any module that holds data. The assigner asks for the move a person must allow before it writes the want (ADR
|
||||||
|
0539 §14). The old node's want is written as removed, and its data item stays on that node's disk, with its copies
|
||||||
|
in that node's repository, until the operator answers (ADR 0429 §6). On its new node the recovery module starts
|
||||||
|
with an empty directory: `kept-points` lists nothing of the old node's, and a `restore-kept` of a point left there
|
||||||
|
answers `missing`. Its `from-backup: yes` then asks the new node's backup holder, which holds no copy of it, so
|
||||||
|
`restored` says `failed` with `restore point missing` and §300 holds the revert. The placement verb asks the
|
||||||
|
recovery module nothing, and §554 no longer refuses a move while a point younger than 90 days is listed.
|
||||||
|
- **An act a move cuts off.** When its node's want is written as removed, the old instance takes no new call
|
||||||
|
(answering `error` naming the move) and, before it stops, ends its running act through its failure path (§516):
|
||||||
|
a restore past its removal puts the aside back under the live names and sets the consumers back; then it ends
|
||||||
|
every accepted act, the running one included, with its ending event, `outcome` `failed` and `error` `stopped`.
|
||||||
|
- **A stop it could not finish** (the old node gone or killed): the new instance, at its start, reads the seat's
|
||||||
|
stream as §556 has it, and ends `failed` with `stopped` every act whose `restore-started` or acceptance (its
|
||||||
|
`ended` or `restored` missing) the stream holds with no ending event, and writes `aside-unrestored` for each such
|
||||||
|
restore, naming the old node, since its aside is on the old node's disk.
|
||||||
|
- **Who asks again.** The node agent and the backup holder hear those endings (§560, §563); the node agent asks
|
||||||
|
again the new holder, which it finds from the catalog half's claims of `mesh-recovery`, and the backup holder
|
||||||
|
starts a put-off item again on a `stopped` `restored`.
|
||||||
|
|
||||||
|
Why: the operator's answer (the knowledge base's review of ADR 0672, R6); the ending of a cut-off act is the
|
||||||
|
design's (round 1 of this batch's review, running and testing R2, health and events H1). How it is checked: unit
|
||||||
|
(assigner), a placement that moves the holder of `mesh-recovery` while points are listed is made, asked as ADR
|
||||||
|
0539 §14 has it; whole (recovery module), on an empty directory a restore of an unknown point says `restore point
|
||||||
|
missing`; a move during a restore after its removal leaves the live data as before and ends the act `stopped`; a
|
||||||
|
new instance whose old one was killed during a restore ends that act `stopped` and writes `aside-unrestored`; a
|
||||||
|
put-off dump starts again after it.
|
||||||
|
- §563 **When a dump and a restore start at one moment, the dump gives way.** (§554) Each side says its start before
|
||||||
|
it reads the other's:
|
||||||
|
- **The backup holder** of G, for the item of the holder of `mesh-broker` (read from the seat list's definition
|
||||||
|
and the catalog half's claim, §554), says `item-started`, then reads `mesh-recovery`'s `restore-started` and
|
||||||
|
`restored`, last per subject, once more. When a restore runs (§560), it ends the item at once with `item-ended`,
|
||||||
|
`outcome` `put-off` and `restore` naming that act, having read nothing of the bus, and starts the item again when
|
||||||
|
it hears `restored` with that `act`.
|
||||||
|
- **The recovery module** says `restore-started`, then reads the item events of the bus's item. While an
|
||||||
|
`item-started` has no `item-ended`, it waits, and takes no aside.
|
||||||
|
- **Said means acknowledged.** Each side reads the other's only once the bus acknowledged its own start event on
|
||||||
|
its stream.
|
||||||
|
|
||||||
|
Since each side says its start before it reads, at least one side sees the other, and the backup holder always
|
||||||
|
gives way, so the two never overlap. A dump that has run since before the restore began is waited for. The backup
|
||||||
|
holder ends every item of its own that it said started and never ended, at its start, after its read of §556, with
|
||||||
|
`item-ended`, `outcome` `failed` and `error` `stopped`, so no restore waits on a dump that no longer runs. Every
|
||||||
|
`item-started` and `item-ended` carries `at`, and `item-ended` its `outcome` (`done`, `failed` or `put-off`).
|
||||||
|
- **A put-off dump is that night's backup.** The operator, 2026-11-11 about 14:05 CET at lead-47's terminal: an
|
||||||
|
item ended `put-off` is neither a failed night nor a missed one (ADR 0235 §13, §21 hold): the item runs when
|
||||||
|
`restored` is heard, and the night is the outcome of that run. The item's last good backup ages as before, so
|
||||||
|
`backup-stale` is raised only by its own age rule, never for the put-off itself. `backed-up` (§302) lists a
|
||||||
|
put-off item with the restore's `act` and since when; `backup-waits` names it after 60 minutes (§561).
|
||||||
|
|
||||||
|
Why: §554 left open which side gives way when both start at once (round 3, running and testing, item 1); how a
|
||||||
|
put-off item counts is the operator's answer (the knowledge base's review of ADR 0672, R5). How it is checked:
|
||||||
|
unit (backup holder and recovery module against a fake bus), both orders of "say, then read" in both sides, each
|
||||||
|
ending with no overlap; whole (backup holder, recovery module, the real bus), a dump and a restore asked at one
|
||||||
|
moment never overlap and the item runs after `restored`; a put-off item raises no `backup-stale` and is not counted failed; a backup holder
|
||||||
|
restarted during an item ends it `failed` with `stopped`, and a waiting restore then starts.
|
||||||
|
- §564 **The cap is a setting, an act that would pass it is refused before it removes anything, and a failed act
|
||||||
|
leaves no half-made point or useless aside.** (§554, §557)
|
||||||
|
- **The settings.** The cap of the data item `points` is the recovery module's setting `points-cap`, 10 GiB unless
|
||||||
|
set, and its fill mark the setting `points-filling-mark`, 80 % unless set, both read at its start, as §557 has a
|
||||||
|
bound.
|
||||||
|
- **Before it writes.** Before it writes anything, `snapshot-kept`, `recovery_take` and the aside of
|
||||||
|
`restore-kept` add up the bytes the bus states for each bus object they take. An act that would pass the cap
|
||||||
|
ends `failed` with `error` `cap`, naming the cap, that size and the directory's fill, before any aside is taken
|
||||||
|
and so before any live object is removed. A `snapshot-kept` that ends so holds the move as a failed backup does
|
||||||
|
(§296). A point or an aside that passes the cap while it is taken (the stream grew) ends its act the same way.
|
||||||
|
- **Brought back.** A point brought back from the backup (`from-backup: yes`, §516) is not counted against the
|
||||||
|
cap: it lies beside its path only while its restore runs, and is removed when the restore ends.
|
||||||
|
- **On a failure.** An act that ends `failed` removes its point under a temporary name (§516) then, not only at
|
||||||
|
the next start. An aside whose record ends at `set aside` (the live objects were never removed) is removed when
|
||||||
|
its restore fails or stops before the removal, and at the start, since the live data was never touched.
|
||||||
|
|
||||||
|
Why: the cap is a bound a whole test sets (§557), and a restore refused for size after the removal would leave the
|
||||||
|
module's data only in an aside (round 3, running and testing, item 2 and its notes). How it is checked: whole
|
||||||
|
(recovery module, with small settings), a snapshot passing the cap ends `failed` and holds the move; a restore whose
|
||||||
|
aside would pass the cap is refused with the live data untouched; `points-filling` written past the mark (§561); a
|
||||||
|
failed point leaves no temporary name; an aside left at `set aside` by a stopped restore is removed at the start.
|
||||||
|
- §565 **The grants part reads the restore points' names through `kept-points`, and composes without them until it
|
||||||
|
answers.** (§554) The bus names of the recovery module's account include those a restore point names (§554). The
|
||||||
|
grants part reads them by its `invokes` of `seat:mesh-recovery.kept-points`, a kept call (ADR 0668 §1). It asks
|
||||||
|
again on every `ended` with `outcome` `done`, every `point-removed` and every `expiry-ended` of `mesh-recovery`,
|
||||||
|
which it consumes (ADR 0668 §4), so a point's names are granted before any restore of it. Until `kept-points`
|
||||||
|
first answers after a start, the grants part keeps the names it last granted from it, kept in its state
|
||||||
|
`memberships` with the account, and adds the catalog half's kept entries (§443); it takes no name away before
|
||||||
|
that answer, and says the wait in `grants_first_views` (§556). The edges between the two (kind 5, the grants part has acted for the recovery module's account; kind 6,
|
||||||
|
the recovery module serves `kept-points`) are a cycle of delivery edges, delivered as one step (§49). Why: the
|
||||||
|
account must follow the points without the grants part reading another part's state (ADR 0596; round 3, seams and
|
||||||
|
tools' notes; running and testing R3). How it is checked: unit (grants part), a restarted grants part with
|
||||||
|
`kept-points` unanswered keeps a point's names it granted before, and a point's old-section names are added after
|
||||||
|
an `ended` and taken away after its `point-removed`.
|
||||||
|
- §566 **Two more hand tools: put an aside back, and cancel a waiting act.** (§554, §516) Each is of class `act`,
|
||||||
|
with callers `operator` and `sessions`, checked by the identity of who asked (§554), written first in the hand-act
|
||||||
|
log of the seat `mesh-hand-acts` with the caller the bus proved and `why`, and an act of its own that runs one at a
|
||||||
|
time (ADR 0672):
|
||||||
|
- `recovery_restore_aside` (`module`, `kept`, `id`, `why`) restores an aside under the live names it was taken from,
|
||||||
|
for an aside whose record ends at `removed` that no running act holds (the case `aside-unrestored` names, §561).
|
||||||
|
It refuses, naming them, while live objects of those names exist (an aside taken by `recovery_aside` is put
|
||||||
|
back by this tool too, the refusal naming `recovery_aside`'s aside when the names are live), and it ends with
|
||||||
|
`restored`.
|
||||||
|
- `recovery_cancel` (`act`, `why`) ends an accepted act that has not begun its work (one waiting on the dump, §563)
|
||||||
|
with its ending event, `outcome` `failed` and `error` `cancelled`. It refuses an act that has begun, naming its
|
||||||
|
step, since a restore cut off after its removal is put back only by its own failure path (§516).
|
||||||
|
|
||||||
|
Why: a module's tools recover what a person may need to recover (*Tools are how a module is spoken to*; round 3,
|
||||||
|
seams and tools' notes). How it is checked: whole (recovery module), an aside left at `removed` put back by
|
||||||
|
`recovery_restore_aside` and refused while the live names exist; a waiting act cancelled and a running one refused.
|
||||||
|
- §567 **A restore point is checked by the digest of its bytes before it is restored.** (§516) A point's record
|
||||||
|
carries `digest`, the `sha256:` digest of each bus object's snapshot file, written when the point is renamed whole
|
||||||
|
(§516). The same digests are kept on the bus, apart from the bytes: in the recovery module's own state `digests`
|
||||||
|
(its kept data, by the template `state`), one key per point, its `snapshot` escaped as a key's name is (§73),
|
||||||
|
written before `ended` is said and deleted when the point is removed (§551); about 0.3 KiB a key, capped at 4 MiB.
|
||||||
|
`kept-points` lists the digests, and `ended` carries them with the point. Before a restore takes any aside, it
|
||||||
|
computes the digest of the bytes it is about to restore, whether from its own directory or brought back by the
|
||||||
|
backup holder (`from-backup: yes`), and compares it with the key in `digests`; the record in the directory is never
|
||||||
|
the reference. The state holds digests only and lists nothing, so §517's "no `bus-points` state" stands for the
|
||||||
|
list. A mismatch ends the act `failed` with `restore point
|
||||||
|
damaged`, naming the point and the bus object, and §300 holds the revert. Why: a point brought back from the backup
|
||||||
|
was restored unchecked (round 3, security and upgrade's notes). How it is checked: whole (recovery module, backup
|
||||||
|
holder), a point whose file and record were both altered after it was taken is refused before any aside is taken.
|
||||||
|
|
||||||
|
## The builder
|
||||||
|
|
||||||
|
- §568 **A transport fault in the builder's own read ends no build key, and a key's error says which kind of fault it
|
||||||
|
is.** (ADR 0664 §1 to §3, ADR 0668 §1 to §3; issue 1612, met again 2026-11-11)
|
||||||
|
- **The builder's own reads.** The builder's reads of the build seats' state `steps` (its own step keys, §467,
|
||||||
|
§481) are kept calls (ADR 0668 §1, §2). A read that meets a transport fault, of ADR 0664 §1's classes or the
|
||||||
|
read's own deadline, changes nothing the builder holds and writes no build key. The builder's watch of `steps`
|
||||||
|
takes up again from its last revision once the bus answers, and a read it made at its start is made again then.
|
||||||
|
Past five minutes it writes `call-unanswered` (ADR 0668 §3). A build key is written `failed` only from a step
|
||||||
|
key's end (ADR 0664 §3).
|
||||||
|
- **The words of a failed key.** A step that ended failed because its third run met a transport fault (ADR 0664
|
||||||
|
§2) gives the build key an `error` that opens `transport fault:`, then the class (`no responders`, `name lookup`,
|
||||||
|
`connection` or `deadline`), the step's seat and node, and the cause of its last run in the build module's words.
|
||||||
|
Every other failure keeps its own opening (`not stored:`, `not pinned:`, `version taken:`, `refused kind:` or the
|
||||||
|
build's own words) and never opens `transport fault:`. The builder's read tools show the error whole, so a reader
|
||||||
|
tells a passing cause from a real one without the journal.
|
||||||
|
- **What builds such a key again.** The operator, 2026-11-11 about 14:15 CET at lead-47's terminal, decided by the
|
||||||
|
record of the builder's retry (number to come), which changes ADR 0664 §3: a key whose error opens `transport
|
||||||
|
fault:` is built again, once, as a new revision of the key (ADR 0429 §18), on the first event after its failure
|
||||||
|
that says its cause passed. Two events say so: the node-engine seat's `running.<node>.<module>` saying `running`
|
||||||
|
for a module whose catalog graph entry claims the build seat the failed step ran on (§546), on any node; and the
|
||||||
|
node-engine's `manifest-reads-changed` of the node the failed step ran on (ADR 0668 §4), which it says when that
|
||||||
|
node is heard again. The builder hears both through its consumers of the node-engine seat, read as §556 has it.
|
||||||
|
It builds a key again at most once per event heard, and only while the key's newest revision is that failure, so
|
||||||
|
one event starts one revision. A revision that fails again on a transport fault is said as every failed key is,
|
||||||
|
its error opening `transport fault:` again, and waits for the next such event. The builder's manifest `consumes`
|
||||||
|
both events.
|
||||||
|
- **Three automatic builds, then the operator is asked.** The operator, 2026-11-11 about 14:55 CET at lead-47's
|
||||||
|
terminal: the builder counts, in the key's newest revision, the revisions events started since the last one a
|
||||||
|
person started (`event-builds`). After three that failed, the next such event starts nothing: the builder asks
|
||||||
|
the operator once, through the seat `operator-channel`'s ask (level `approve`, options *Build once more* and
|
||||||
|
*Leave it*, `about` the key so a newer ask replaces it, ADR 0666 §12), naming the module, the fingerprint and
|
||||||
|
the last error whole. *Build once more* builds one revision, counted as a person's, so the count starts again;
|
||||||
|
*Leave it*, a decline or the ask's expiry leaves the key failed until `builder_build_again` or a new
|
||||||
|
fingerprint. The failure stays said throughout. A key failed for any other cause
|
||||||
|
is never built again on these events. `builder_build_again` (ADR 0668 §5) and the builder's next start build it
|
||||||
|
again too, as before. The builder's read tool of a key names the event that built its newest revision again,
|
||||||
|
`event-builds`, and the open ask.
|
||||||
|
- **Before develop.** These lines rest on the record of the builder's retry, which changes ADR 0664 §3 (in force);
|
||||||
|
it is accepted before G's builder is built from them, and its number replaces "number to come" here.
|
||||||
|
|
||||||
|
Why: a read the builder made met `no responders` and failed a key, which then stayed failed for about 45 minutes
|
||||||
|
(issue 1612, 2026-11-11), against ADR 0664 §3 (a key is not written failed while its step runs on); the retry on an
|
||||||
|
event is the operator's answer. How it is checked: unit (builder), a `no responders` read of `steps` leaves the key
|
||||||
|
`building` and the next revision ends it; a third-run transport fault's key error opens `transport fault: no
|
||||||
|
responders`, and a compile error's does not; a `running` of a holder of that build seat builds the key again once,
|
||||||
|
and a second `running` while the new revision builds starts nothing; a node's `manifest-reads-changed` builds again
|
||||||
|
a key failed on that node; a key failed on a compile error is not built again on either event; after three failed
|
||||||
|
event-started revisions the fourth event asks the operator once and builds nothing, and *Build once more* builds
|
||||||
|
one.
|
||||||
|
|
||||||
|
## The order of a change
|
||||||
|
|
||||||
|
- §569 **A cycle with a build edge is refused, whatever its other edges, and a grant composed from a first view is an
|
||||||
|
edge.** (§49, §558, §374) The indexer's cycle rule (§49) reads every edge of the six kinds in one graph per watched
|
||||||
|
branch. A cycle whose edges are all delivery edges (kinds 2, 4, 5 and 6) is delivered as one step. A cycle with at
|
||||||
|
least one build edge (kind 1 or 3) is refused, whatever its other edges, at the check and at take-in, naming every
|
||||||
|
artifact on it in order with each edge's kind and the manifest word it came from: no build on such a cycle can
|
||||||
|
start before a delivery that waits for that build (ADR 0666 §14). Two kinds of edge enter that graph:
|
||||||
|
- **A seat verb a build calls.** When a build module's step calls a seat verb while it builds (the image build
|
||||||
|
module calling `container-image-registry`'s `mirror` for a base image), its manifest names it in `invokes`, and
|
||||||
|
the indexer derives an edge of kind 3 from that seat's holders to every image artifact the build module builds.
|
||||||
|
The edge is met by the holder that runs when the build starts, whatever its version: it orders a build after a
|
||||||
|
running holder, never after the holder's new version. So the holder's own artifacts are built through its
|
||||||
|
running version, and the edge makes no cycle through them.
|
||||||
|
- **A grant from a first view.** A binding the grants part writes for a holder from its first view of a served
|
||||||
|
answer (design 25 *bindings-first-view* §4 and §9)
|
||||||
|
is an edge of kind 5 from the grants part to that holder. Where the grants part names a field of that answer
|
||||||
|
(§558), an edge of kind 6 runs from the answer's seat holder to the grants part. Its new version must run, so this
|
||||||
|
edge is met only by that version.
|
||||||
|
|
||||||
|
The circle of 2026-11-11 was such a cycle: the bus module's image waits, by kind 3, for the registry holder's
|
||||||
|
delivery; the registry holder waits, by kind 5, for its binding `mirrors` from the grants part; and the grants part
|
||||||
|
waited, by kind 6 on `mesh-broker`'s `list` with `binding`, for the bus module's new version: the kind-3 edge waited
|
||||||
|
for a registry that served `mirror`, which needed its binding, which needed the new bus module. It is refused at its
|
||||||
|
check, naming the three artifacts. Design 25 *bindings-first-view* §9 removes the kind-6 edge: the grants part
|
||||||
|
composes a binding from the fields `list` already answers, so it relies on no new field and names none (§558).
|
||||||
|
G's delivery then puts the grants part before the bus module's build. Why: the circle mixed a build edge and a
|
||||||
|
delivery edge, and no rule saw it (issue 1966, notes 203 and 204; the operator, 2026-11-11 13:30 CET, on design
|
||||||
|
25's §9). How it is checked: unit (indexer's graph), a cycle of kinds 3, 5 and 6 is refused naming its three
|
||||||
|
artifacts and their kinds; a cycle of kinds 5 and 6 alone is one step; a build module's `invokes` of `mirror` gives
|
||||||
|
a kind-3 edge to its image artifacts; the image registry's own image, built through its running holder, is not
|
||||||
|
refused.
|
||||||
|
|
||||||
|
## Asks to the operator
|
||||||
|
|
||||||
|
- §570 **An ask the router refuses is heard by its asker, and no asker asks for longer than its level allows.**
|
||||||
|
(ADR 0259 §3, §4) The kind behind it is an asker left waiting on an ask the router never took (issue 1610; met
|
||||||
|
again 2026-11-11, when the bus module's three `nats_recreate` asks were refused at take-in and their tool kept
|
||||||
|
saying the operator had not answered).
|
||||||
|
- **The router says the refusal.** The router (the holder of `operator-channel`) says every ask it refuses at
|
||||||
|
take-in, for each cause ADR 0259 §4 gives as it holds, on that asker's
|
||||||
|
`mesh.seat.operator-channel.event.decided.<asker>`. The event carries `outcome` `refused`, the ask's `id`, `why`
|
||||||
|
in the router's words and `at`, as an ask's end without a warrant is said (ADR 0259 §3).
|
||||||
|
- **Every asker ends its request on it.** mesh-sdk's asker client gives its caller `refused` with `why` as soon as
|
||||||
|
it hears it. An asker's tool or act that waits on that ask answers `refused` with why, never "not answered yet";
|
||||||
|
the bus module's `nats_recreate` and `nats_drop` are among them.
|
||||||
|
- **The lifetime is held where every ask is made.** mesh-sdk's asker client changes in G's mesh-sdk release, which
|
||||||
|
every asker is built against (§47). mesh-sdk's asker client, through which every asker publishes
|
||||||
|
an ask, refuses before it publishes an ask whose expiry passes the bound of its highest option level (`approve`
|
||||||
|
24 hours, `destroy` 10 minutes, ADR 0259 §4), naming the level and the bound. The bus module's keeper asks for
|
||||||
|
its level's bound in place of its fixed 12 hours (`AskLasts`).
|
||||||
|
- **The operator sees a refused ask.** The operator, 2026-11-11 about 14:15 CET at lead-47's terminal: the router
|
||||||
|
keeps each ask it refuses at take-in in its bucket `asks` under `<asker>.<id>` as a closed record, with `outcome`
|
||||||
|
`refused`, `why` in the router's words and `at`, for 30 days like every closed record (ADR 0259 §3). It writes
|
||||||
|
the record only by a create: when `<asker>.<id>` holds a record already (an open ask, its tickets with it), the
|
||||||
|
refusal writes nothing there and is said on `decided` alone. The operator, 2026-11-11 about 15:15 CET ("just make
|
||||||
|
it configurable"): the router keeps at most `refused-kept` refused records per asker, a setting of the router,
|
||||||
|
20 unless set, removing the oldest first, each also gone after its 30 days, each removal written in its journal. The seat's
|
||||||
|
`asks` lists it with that outcome and words, as an ask that ended.
|
||||||
|
|
||||||
|
Why: ADR 0259 §4 refuses such an ask on the decided subject and bounds a destroy option at 10 minutes, and neither
|
||||||
|
reached the asker; the list is the operator's answer. How it is checked: unit (mesh-sdk's asker client), a table
|
||||||
|
over the levels in which an expiry at the bound is published and one past it is refused before it is published,
|
||||||
|
and a `refused` that ends the request with why; the code review refuses an ask built outside the client; whole
|
||||||
|
(router, bus module), a refused ask is said on `decided`, a refusal of an id that is open leaves the open record and its tickets as they
|
||||||
|
were, a twenty-first refusal of one asker removes its oldest, `asks` lists it `refused` with the router's words, and
|
||||||
|
`nats_recreate` answers `refused` with those words.
|
||||||
|
|
||||||
|
## A module's packages
|
||||||
|
|
||||||
|
- §571 **A mesh package's entry in a lock file is written by the build, never by hand.** (ADR 0573 §2, §4; §47,
|
||||||
|
§478, §504) A module's `package.json` names a mesh package (one whose name §504 maps to a catalog artifact) with the
|
||||||
|
range `*`, or with the oldest version it accepts (ADR 0573 §2). Its committed `package-lock.json` may hold any entry
|
||||||
|
for that package, or none.
|
||||||
|
- **What the build writes.** The Node and TypeScript build module removes every entry of a mesh package from the
|
||||||
|
workspace's lock before it installs. It then writes the entry from the version the planner read and the
|
||||||
|
integrity the package registry gives for that version (ADR 0573 §2). In a delivery group's check where a member
|
||||||
|
publishes the package, it writes the entry from that member's head, packed for the check, with the packed
|
||||||
|
tarball's integrity (ADR 0573 §4, ADR 0500 §4). Every other entry is installed as the lock names it and checked
|
||||||
|
against its integrity (*Every dependency comes by the version its lock file names*).
|
||||||
|
- **Before its first publication.** A package of which no version is published yet (`npm-package-registry`'s
|
||||||
|
`versions` answers none, as for the packages G itself publishes first) is reached only in a group's check, from
|
||||||
|
its member's head. Outside a group, the edge of kind 1 (§47) builds the dependent after the package's first
|
||||||
|
publication, which G's delivery orders.
|
||||||
|
- **The check's lock rule** never refuses a mesh package's entry, nor its absence.
|
||||||
|
- **The reuse key** of a build takes the versions it wrote for mesh packages, as the fingerprint takes them (ADR
|
||||||
|
0573 §2), so a build is never reused across two of them.
|
||||||
|
|
||||||
|
Why: ADR 0573 §2 has the build write a mesh package's version into the workspace, and a lock made by hand holds
|
||||||
|
the integrity of a locally packed tarball, which the published one never matches (develop question of the forge
|
||||||
|
module's developer, 2026-11-11). How it is checked: unit (Node build module), a lock naming a local tarball's
|
||||||
|
integrity for a mesh package is built with the registry's version and integrity; a lock without the entry is built
|
||||||
|
alike; a non-mesh entry with a wrong integrity is refused; whole (G's group check), the forge module's tools are
|
||||||
|
built against the head of the member that publishes the package, packed.
|
||||||
|
|
||||||
|
## The builder's forms
|
||||||
|
|
||||||
|
- §572 **The builder's process answers a package's name, and its tools ask it.** (§478, §504) The mapping from a
|
||||||
|
package's name to its module and artifact is the builder process's own, from its view of the catalog half (§348).
|
||||||
|
The seat `mesh-builds`' `reserved`, given `name`, is answered by the builder's process from that view. The
|
||||||
|
builder's tools bundle holds no catalog view: `builder_versions`, asked by a name, calls `reserved` (or, for a
|
||||||
|
module, `reserved` with `module`) through its `invokes` and answers what the process answers. Why: one mapping
|
||||||
|
and one view, in the part that keeps them (ADR 0596 §2; develop question BL7's name part). How it is checked: unit
|
||||||
|
(builder), `reserved` with an npm name and with a Go module path answered from the view; whole (builder),
|
||||||
|
`builder_versions` by name answers the same as `reserved`.
|
||||||
|
- §573 **The build seat's ask carries `version`.** (§370, §458) The ask of each build seat (`node-build-go`,
|
||||||
|
`node-build-node` and the image build seat) gains the field `version`: the version `MAJOR.MINOR.PATCH` the builder
|
||||||
|
reserved for the build (§369), or empty for a build that reserves none (§371, §373). The field is part of the build
|
||||||
|
seats' contract package, beside the ask's other fields. The builder fills it when it asks, and each build module
|
||||||
|
reads it and passes it as `MESH_VERSION` (§370), passing none when it is empty, so the build stamps none (§458). A
|
||||||
|
build module of before G ignores the field and stamps nothing. Why: §370 named no field (develop question of the
|
||||||
|
builder's developer on CT5). How it is checked: unit (build seats' contract), `version` read and an empty one
|
||||||
|
read as none; whole (Go and TypeScript build modules), a build asked with a version carries it.
|
||||||
|
- §574 **`toolchain-agreed` carries `digests` as a list.** (§472, §495) The event's field `digests` is a list, each
|
||||||
|
item `{digest, nodes}`: the `sha256:` digest of the toolchain program and the nodes that reported it at the agreed
|
||||||
|
version, sorted by digest, with each item's `nodes` sorted. It replaces the field `digest`, which the event no
|
||||||
|
longer carries; a kept event of before G that carries `digest` alone is read as
|
||||||
|
one item with no `nodes`. Why: §472 names one digest per group of nodes, and a list keeps two digests of one version apart
|
||||||
|
(develop question of the contracts developer). How it is checked: unit (mesh-builds' contract), the list read, and
|
||||||
|
an event of before G carrying `digest` alone read as one item with no `nodes`, so a reader of G refuses none
|
||||||
|
and nothing waits for the next agreement.
|
||||||
|
|
||||||
|
## What a node-engine says of a build
|
||||||
|
|
||||||
|
- §575 **A want held for its build says how the build stands.** (§524) The operator, 2026-11-11 about 14:05 CET at
|
||||||
|
lead-47's terminal: the words "the build of <module> at <fingerprint> is not done" are the assigner's, the reason
|
||||||
|
of its hold under its first rule (no want for a fingerprint whose build is not done, ADR 0429 §6). That reason now
|
||||||
|
says how the build stands, from the builder's `build.ended` the assigner already consumes and from the build it
|
||||||
|
waits on: a failed build reads `the build of <module> at <fingerprint> failed: <the error>`, the error whole as
|
||||||
|
`build.ended` carries it, `transport fault:` included (§568); a build that runs reads `the build of <module> at
|
||||||
|
<fingerprint> is being built`. The assigner says it in its wait for that module, which the watchman's
|
||||||
|
`delivery-waits` names; the node-engine reads no build state for it (ADR 0596). "Is not done" is said no more.
|
||||||
|
Why: the operator's answer; a failed build said as not done left the operator and the watchers waiting for a
|
||||||
|
build that had ended (round 1 of this batch's review, seams and tools T1, placed the words in the assigner). How
|
||||||
|
it is checked: unit (assigner), a module whose build ended failed is held saying `failed:` with the error, and one
|
||||||
|
whose build runs saying `is being built`.
|
||||||
|
|
||||||
|
## The tool runner, and kept data at run time
|
||||||
|
|
||||||
|
- §576 **A bundle reads its tool runner's capability words through one call.** (§488, §545, §559) The tool runner
|
||||||
|
answers the runtime call `mesh/capabilities` with `{words}`, the capability words it states (§545). mesh-sdk's
|
||||||
|
bundle, in Go and in TypeScript, makes that call once, at its first call that needs a word, and keeps the answer
|
||||||
|
for as long as it runs. A bundle lives no longer than the tool runner that started it (its channel is that tool
|
||||||
|
runner's standard input and output), so after a restart of the tool runner the bundle is started again and reads
|
||||||
|
the words again. A tool runner of before G answers `mesh/capabilities` as an unknown call, which the bundle reads as
|
||||||
|
no word stated, so a call of a family G adds fails at once, naming its word and the node (§488). A bundle learns
|
||||||
|
its node from `MESH_NODE`, which the tool runner sets in the environment of every bundle it starts, read alike in Go
|
||||||
|
and in TypeScript. Why: §488 named no channel (develop question of the mesh-sdk developer). How it is checked: unit
|
||||||
|
(tool runner), `mesh/capabilities` answers the stated words; unit (mesh-sdk, both languages), the words read once,
|
||||||
|
an unknown-call answer read as none, and the node read from `MESH_NODE`.
|
||||||
|
- §577 **A part reaches the kept data its `requires` declares through its binding, never by an old name.** (§529;
|
||||||
|
ADR 0595 §1, §9; ADR 0619 §2)
|
||||||
|
- **A bundle** reaches it only through the tool runner's `mesh/` calls by its local name (ADR 0595 §9), which the
|
||||||
|
tool runner resolves in the module's membership binding.
|
||||||
|
- **A process with an account of its own** reaches it by its binding: mesh-sdk's process package gains `Binding`,
|
||||||
|
which takes a local name and gives the entry's bus names (bucket, stream and subjects, object stores). It asks the
|
||||||
|
seat `mesh-broker`'s `show` for the module and the local name at the process's start, as a kept call (ADR 0668 §1)
|
||||||
|
that the process's `bus` names in `invokes`. It asks again when it hears `mesh-broker`'s `recreated` or `dropped`
|
||||||
|
for that entry, which the process consumes. Until `show` answers, the process acts on nothing that needs the entry
|
||||||
|
and its health says it waits, naming the entry (ADR 0283).
|
||||||
|
- **The old name** (mesh-sdk's opening of an essential bucket by its declared name) is for a foundation part's old
|
||||||
|
`state` section alone (ADR 0619 §2). A part that declares an entry in `requires` opens it by `Binding`; the forge
|
||||||
|
bridge's `performed` is among them, moved so in G's change.
|
||||||
|
- **The validator's rule for the finding words** (§529) accepts the old stream `<module>-findings` only for a part
|
||||||
|
on the foundation list (ADR 0619 §3 as ADR 0666 §4 changes it). It refuses that stream for every other part, whose
|
||||||
|
finding stream it requires in the template form: `finding-events`, by the template `events`, its entry listing
|
||||||
|
`finding-written.*`, `finding-cleared.*` and `findings-stated.*`.
|
||||||
|
|
||||||
|
Why: a part's kept data is the bus module's to name and the part's to ask for (ADR 0595 §1, §7), and §529 left the
|
||||||
|
run-time path and the validator's row open (develop question of the watchman's developer). How it is checked: unit
|
||||||
|
(mesh-sdk's process package), `Binding` answered from `show`, asked again on `recreated`, and waiting while
|
||||||
|
unanswered; unit (forge bridge), `performed` opened by its binding; unit (manifest validator), a foundation part's
|
||||||
|
old finding stream accepted, another part's refused and its template form accepted.
|
||||||
|
|
||||||
|
## The indexer's forms
|
||||||
|
|
||||||
|
- §578 **`manifest-digest` carries its prefix, and the key does not.** (§506, §445) The catalog graph entry's field
|
||||||
|
`manifest-digest` is `sha256:` followed by the 64 hex digits, as every digest a record names. The module's value
|
||||||
|
and §445's `manifests` key stay the 64 hex digits as on main, since a key's name takes no `:` (§73), and mesh-sdk's
|
||||||
|
catalog client gives the bare digits as today. The indexer writes all three from the one digest it computed at take-in.
|
||||||
|
Why: one digest in two forms, the field's as the records write a digest and the key's as a key's name allows
|
||||||
|
(develop question of the indexer's developer). How it is checked: unit (indexer), the entry's field after its
|
||||||
|
prefix equals the key's name and the module's value.
|
||||||
|
- §579 **The indexer keeps the records pinning each revision, and removes a revision only on an event.** (§153,
|
||||||
|
§178, §216)
|
||||||
|
- **Where.** The indexer, a foundation part, keeps its old `state` section `pins`: one key per catalog graph
|
||||||
|
revision, `<branch>.<revision>` (the watched branch and the revision's id, each escaped as a key's name is, §73),
|
||||||
|
whose value is the list of delivery record ids that pin it. A list of ids is kept rather than a count, so a
|
||||||
|
`pinned` heard twice pins once. At about 20 revisions pinned a day for 90 days, about 1,800 keys of about 0.2 KiB
|
||||||
|
each, it is capped at 4 MiB (an estimate).
|
||||||
|
- **Applying `pinned` and `freed`.** The indexer adds or removes a record's id by compare-and-set, and only then
|
||||||
|
acknowledges the event on its durable consumer of `mesh-delivery`'s events (§153). That consumer, when first
|
||||||
|
made, starts at the stream's first message. A `freed` said while it was stopped is applied when it comes back,
|
||||||
|
and one applied twice changes nothing. A `pinned` of a revision the indexer no longer holds writes its key with
|
||||||
|
the record's id and `missing: true`, and the finding `pin-missing` (scope the indexer, id the revision) naming
|
||||||
|
the record, which `indexer_unpin` clears.
|
||||||
|
- **The gate states its pins.** At each start the gate says `pinned` again for every revision each record it keeps
|
||||||
|
pins, then once `pins-stated` (`at`), so pins said before the indexer's consumer existed, or older than the
|
||||||
|
stream keeps, are heard again; the set form absorbs the repeats.
|
||||||
|
- **Current.** A revision is current while it is the newest revision the indexer took in on its watched branch,
|
||||||
|
whichever watched branch that is, or the newest revision of an open candidate (its `candidates.<group>`). It stops
|
||||||
|
being current when a newer revision of its branch is taken in, or when the candidate's `heads-replaced` is heard
|
||||||
|
(its heads replaced, or its pull request closed) or the candidate is taken in.
|
||||||
|
- **Removal.** When a revision's list is empty and it is not current, the indexer removes its revision object and
|
||||||
|
its key, and its entry objects as §179 has it, but only while its consumer of `mesh-delivery`'s events is caught
|
||||||
|
up (none of its messages pending), so a `pinned` said before is applied first, and only once it has applied a
|
||||||
|
`pins-stated` said after its state `pins` was made. It judges on applying `freed`, on a revision ceasing to be
|
||||||
|
current, on being caught up, and at its start after both of these hold, when it judges every kept revision, so a
|
||||||
|
stop between a take-in and a removal keeps nothing for ever. Never on a timer.
|
||||||
|
- **Inputs.** A catalog graph revision names no input revision. "The input revisions it names" (§178) are an
|
||||||
|
assignment graph revision's catalog revisions, which a delivery record pins itself (§153), so the indexer keeps
|
||||||
|
each by its own list alone.
|
||||||
|
- **The assigner** keeps its pins of assignment graph revisions in the same form and by the same rules: its old
|
||||||
|
`state` section `pins` (it is a foundation part, ADR 0619 §1), one key per assignment graph revision, capped at
|
||||||
|
4 MiB; a revision is current while it is the newest the assigner wrote, or the newest it wrote for an open
|
||||||
|
candidate; its tools are `assigner_pins` and `assigner_unpin`, as the indexer's below.
|
||||||
|
- **Its tools.** `indexer_pins` reads each kept revision with the records that pin it, whether it is current and
|
||||||
|
why, and the store's fill against its cap. `indexer_consumer` reads each of the indexer's durable consumers: its
|
||||||
|
stream, name, acknowledged sequence, the messages pending, and the last event applied with its `at`. Both are
|
||||||
|
of class `read`. `indexer_unpin` (`revision`, `record`, `why`; class `act`, callers `operator` and `sessions`,
|
||||||
|
written in the hand-act log first) removes one record's id from a revision's list, for a `freed` that was lost,
|
||||||
|
and the removal rule then applies.
|
||||||
|
|
||||||
|
Why: §153 and §178 said what is kept, not where or how it is counted (develop questions IX17 and IX18). How it is
|
||||||
|
checked: unit (indexer), a revision pinned twice by one record and freed once is removed; a `freed` applied twice
|
||||||
|
changes nothing; a revision of a second watched branch kept while current; a candidate's revision removed on
|
||||||
|
`heads-replaced`; a revision that stops being current while a `pinned` of it is pending is kept; a `pinned` of a
|
||||||
|
removed revision writes `pin-missing`; `indexer_unpin` frees a revision; whole (indexer, gate), a `freed` said
|
||||||
|
while the indexer was stopped is applied after its start; a `pinned` said before the indexer of G first started is
|
||||||
|
heard through the gate's restatement; an indexer stopped between a take-in and a removal removes the revision at
|
||||||
|
its start.
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
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
|
||||||
|
judges and states its own kinds from its own truth (§384); no bundle reads the whole state to state another's
|
||||||
|
findings. Its `findings-stated` carries `kinds`, the kinds it states, and the writer's statement deletes only keys of
|
||||||
|
those kinds. The keeper sets its view of that observer, node and set of kinds from the statement, and clears only
|
||||||
|
conditions of those kinds that the statement does not name. A statement with no `kinds` (a writer of a part with
|
||||||
|
one bundle) covers every kind, as before. Why: a statement that deletes every key it does not state would clear
|
||||||
|
another bundle's findings (develop question of the forge module's developer, GIT14). How it is checked: unit
|
||||||
|
(writer, both languages), a statement with `kinds` deletes no key of another kind, and a write of another kind is
|
||||||
|
refused; whole (keeper), two bundles' statements on one node each keep the other's conditions open.
|
||||||
|
- §581 **A `seen` key's 30 days are judged on each step end, with no timer.** (§487) The forge module writes `at` in
|
||||||
|
each `seen` key's value, the time of the `step-ended` that wrote it. On each `step-ended` it handles, and at its
|
||||||
|
start, it deletes the `seen` keys whose `at` is more than 30 days old, at most 100 for each event, the oldest first,
|
||||||
|
so the bus keeps no key time-to-live and no template option is added; its tool `git_seen_expire` (class `act`,
|
||||||
|
callers `operator` and `sessions`, written in the hand-act log) runs the same removal now. The forge module being a foundation part
|
||||||
|
(§584), its state `failed-steps` is in its old `state` section, and a bundle reaches it through the tool runner's
|
||||||
|
state call by its name, as every old section is reached. Why: §487's 30 days needed
|
||||||
|
a trigger, and an event the module already handles is one (develop question of the forge module's developer). How
|
||||||
|
it is checked: unit (forge module), a `seen` key older than 30 days is deleted at the next `step-ended`, and a
|
||||||
|
younger one is kept.
|
||||||
|
- §582 **`reserved` by name answers a released version from the catalog.** (§381, §478, §369) Given `name` and
|
||||||
|
`version` with no reservation of that version (§369 deletes a reservation once its version is released), the
|
||||||
|
builder finds the module from the name (§572) and asks the seat `mesh-catalog`'s `versions` for that module, as a
|
||||||
|
kept call in its `invokes`. When the catalog holds that version released, `reserved` answers `released` with the
|
||||||
|
artifacts and the digests the release recorded, and the registry holder answers its publish as held when the
|
||||||
|
digest is the release's, storing nothing (§381). A version neither reserved nor released, or a name no entry
|
||||||
|
carries, is answered `error`, naming which, and the holder refuses the publish. Why: the holder knows only the name,
|
||||||
|
and the module is the builder's own mapping (develop question of the forge module's developer). How it is checked:
|
||||||
|
unit (builder), `reserved` for a released version answers `released` with its digests, and an unknown version
|
||||||
|
`error`; whole (registry holder, builder), a publish of a released version at its digest stores nothing.
|
||||||
|
- §583 **A manifest's first `version` is §368's.** The `version` G writes into the forge module's and the image
|
||||||
|
registry module's manifests is the `MAJOR.MINOR` of the version §372 fills for each, read through
|
||||||
|
`builder_versions`, and `0.1` for a module with none published (§368); their old values (`"1"` and `"2"`) carry
|
||||||
|
nothing over. Why: §368 answers it (develop questions GIT15 and MAN1). How it is checked: as §368.
|
||||||
|
- §584 **The forge module and the image registry module are foundation parts.** (§6, §529, §569; ADR 0619 §1 to §3)
|
||||||
|
The operator, 2026-11-11 about 14:30 CET at lead-47's terminal: ADR 0619 §1 is followed as written. The bus
|
||||||
|
module's build calls both before the bus module can answer, the forge for its source and the image registry's
|
||||||
|
`mirror` for its base image, so both are foundation parts.
|
||||||
|
- **The list.** The manifest validator's list (§6, ADR 0619 §3) gains the holder of the seat `git` (the forge
|
||||||
|
module, `gitea`) and the holder of `container-image-registry` (the image registry module, `distribution`) in G's
|
||||||
|
change.
|
||||||
|
- **Their kept data.** Each keeps its kept data in its old sections (ADR 0619 §2): its state `findings` and its
|
||||||
|
finding stream `<module>-findings` as §529 has a foundation part declare them, and every other state in its old
|
||||||
|
`state` section, the forge module's `failed-steps` among them (§581). The image registry module's `holds`,
|
||||||
|
`windows` and `mirrors` go back from their template entries to its old `state` section under the names they had
|
||||||
|
there. The operator, 2026-11-11 about 15:15 CET ("whatever must be done to not end up in a cycle"): at its first
|
||||||
|
start, before it serves anything, the image registry of G copies every key of its template `holds`, `windows` and
|
||||||
|
`mirrors` into its old sections, from its own data alone, and says in its journal and its read tool how many keys
|
||||||
|
it copied of each; a key already in the old section stays. This needs no other part's answer and adds no edge,
|
||||||
|
so it can close no cycle; holding its delivery until the template state is empty could wait for ever, since the
|
||||||
|
running registry keeps writing it. The template entries, no longer declared, then become orphans that `orphans`
|
||||||
|
lists, removed only by the operator's `drop` (ADR 0595 §4, §5), as §529 has it for the healers' old stream.
|
||||||
|
- **The delivery order.** The running image registry, of its build before G, serves `mirror` only once its bindings
|
||||||
|
are composed, and both the bus module's new build and the image registry's own new build ask it for their base
|
||||||
|
images. So the grants part with design 25 *bindings-first-view* §9 is delivered first, alone, and composes the
|
||||||
|
running registry's three bindings from `list`'s fields. Then
|
||||||
|
the image registry's and the bus module's builds of G are built through the running registry's `mirror` (edges of
|
||||||
|
kind 3, §569), and delivered by the edges of §49. Once the image registry of G runs, its state is in the old
|
||||||
|
sections, which the grants part creates as it creates every foundation part's, and no binding of a first view is
|
||||||
|
needed for it.
|
||||||
|
|
||||||
|
Why: the operator's answer; the list and the order follow ADR 0619 §1 and §3 and §569. How it is checked: unit
|
||||||
|
(manifest validator), both manifests of G's heads accepted with their old sections, and a template entry in either
|
||||||
|
refused; the catalog's validation at G's heads refuses neither; whole (image registry), a first start with keys in
|
||||||
|
its template `mirrors` copies them, says how many, and then serves them; the delivery plan of G puts the grants part's
|
||||||
|
delivery before both builds.
|
||||||
|
- §585 **What the forge module reads from `step-ended`, and the form of its `failed-steps`.** (§39, §475, §487, §581)
|
||||||
|
The forge module's readings where no line spoke, made design lines:
|
||||||
|
- **The fingerprint** of a step is the body's `fingerprint`, the build-input fingerprint, which the runner fills
|
||||||
|
in every `step-ended`. No field of the step's `result` is read for it. A `step-ended` without it writes the
|
||||||
|
forge module's finding `step-unread` (scope the module the step is of, id the run), naming the run, the module and
|
||||||
|
the step, cleared by a later `step-ended` of that step with its fingerprint, so a failure that could not be
|
||||||
|
recorded is seen.
|
||||||
|
- **A failure** is a `step-ended` whose `outcome` is `failed` and whose `status` is `required`. An `optional` or
|
||||||
|
`bypass` step's failure, and a `could not run`, record no failure, as ADR 0666 §11 refuses only a failed
|
||||||
|
`required` step.
|
||||||
|
- **A rerun's pass** clears a failure when the body says `rerun: true` and its `by`, the caller the runtime proved
|
||||||
|
as the runner's verb `rerun` names its callers, is `operator` or `seat:mesh-healers`; any other `by` clears
|
||||||
|
nothing (§39).
|
||||||
|
- **The watched branches** are those of each registration whose git origin is a repository the forge holds, per
|
||||||
|
repository, read through `mesh-catalog`'s `registrations` and kept current on `registration-changed`.
|
||||||
|
- **A `seen` key** `seen.<commit>.<module>` holds `{v, commit, module, fingerprints, at}`: `v` the form's version
|
||||||
|
(1), `fingerprints` every build-input fingerprint the runs named for that commit and module, and `at` as §581
|
||||||
|
has it. Both key forms of `failed-steps` are the forge module's own, defined in its own package, since no other
|
||||||
|
part reads that state.
|
||||||
|
- **The fill** of `failed-steps` that its read tool shows is counted by the forge module from the keys and value
|
||||||
|
bytes it reads, against the state's cap of 64 MiB, and said as counted, since a bundle's state call gives no
|
||||||
|
fill of the bus's own.
|
||||||
|
|
||||||
|
Why: the forge module's developer read these where no line spoke (develop, batch 5); each follows §39, §475, §487
|
||||||
|
and ADR 0666 §11. How it is checked: unit (forge module), a `required` failure recorded and an `optional` one not;
|
||||||
|
a rerun pass by `operator` clears and one by another caller does not; a `seen` value read in its form, and both
|
||||||
|
key forms; a `step-ended` without `fingerprint` writes `step-unread`.
|
||||||
|
- §586 **The client of `reserved` is the seat `mesh-builds`' contract package.** (§381, §478, §582) The forge
|
||||||
|
module's package registry and the image registry module both ask `reserved`. The call is the seat `mesh-builds`'
|
||||||
|
contract, so its client lives where ADR 0573 §1 puts a seat's contract: the package the seat's holder's
|
||||||
|
repository publishes, mesh-delivery's contracts package, which defines `mesh-builds` (§52). That package gains a
|
||||||
|
`mesh-builds` client with `reserved`, its input and its answers (`reserved`, `released`, `error`), and both
|
||||||
|
registry holders use it in place of their own copies. It is not put in mesh-sdk, which keeps no seat-specific
|
||||||
|
verb (ADR 0573 §1). Why: code two modules share has one home, and for a seat's verb that home is the seat's
|
||||||
|
contract package (develop question of the forge module's developer). How it is checked: unit (mesh-delivery's
|
||||||
|
contracts), the client's input and each answer read; the code review finds no second copy in either holder.
|
||||||
@@ -5,6 +5,7 @@ design: 47
|
|||||||
milestone: G
|
milestone: G
|
||||||
updated: 2026-11-11
|
updated: 2026-11-11
|
||||||
decisions:
|
decisions:
|
||||||
|
- "ADR 0500"
|
||||||
- "ADR 0672"
|
- "ADR 0672"
|
||||||
- "ADR 0436"
|
- "ADR 0436"
|
||||||
- "ADR 0670"
|
- "ADR 0670"
|
||||||
@@ -64,9 +65,10 @@ decisions:
|
|||||||
- "ADR 0391"
|
- "ADR 0391"
|
||||||
- "ADR 0363"
|
- "ADR 0363"
|
||||||
- "ADR 0289"
|
- "ADR 0289"
|
||||||
- "ADR 0283"
|
|
||||||
- "ADR 0253"
|
- "ADR 0253"
|
||||||
- "ADR 0240"
|
- "ADR 0240"
|
||||||
|
- "ADR 0283"
|
||||||
|
- "ADR 0259"
|
||||||
- "ADR 0235"
|
- "ADR 0235"
|
||||||
- "ADR 0233"
|
- "ADR 0233"
|
||||||
---
|
---
|
||||||
@@ -79,7 +81,7 @@ file on 2026-11-10, and is cited as "design 47 G §n". A sentence that holds a d
|
|||||||
stayed in the main file, and G builds what it says from G's delivery. A section named in italics is in this part, or,
|
stayed in the main file, and G builds what it says from G's delivery. A section named in italics is in this part, or,
|
||||||
when it is not here, in the main file.
|
when it is not here, in the main file.
|
||||||
|
|
||||||
The part is fourteen files, each read whole, its design lines numbered across them:
|
The part is fifteen files, each read whole, its design lines numbered across them:
|
||||||
|
|
||||||
- [G-1-pipelines-registration-and-steps](G-1-pipelines-registration-and-steps.md): pipelines per module: registration, watched branches, steps and policy, what holds a delivery, approval, groups, dependencies, a publish.
|
- [G-1-pipelines-registration-and-steps](G-1-pipelines-registration-and-steps.md): pipelines per module: registration, watched branches, steps and policy, what holds a delivery, approval, groups, dependencies, a publish.
|
||||||
- [G-2-pipelines-sizes-checks-and-tools](G-2-pipelines-sizes-checks-and-tools.md): pipelines per module: any size, the pipeline makes the check, who may say what, health, recovery, tools, kept data, how G itself is delivered, the choices under ADR 0666 and ADR 0667.
|
- [G-2-pipelines-sizes-checks-and-tools](G-2-pipelines-sizes-checks-and-tools.md): pipelines per module: any size, the pipeline makes the check, who may say what, health, recovery, tools, kept data, how G itself is delivered, the choices under ADR 0666 and ADR 0667.
|
||||||
@@ -95,3 +97,4 @@ The part is fourteen files, each read whole, its design lines numbered across th
|
|||||||
- [G-12-develop-answers-fourth](G-12-develop-answers-fourth.md): the operator's answers of 2026-11-11 noon, round 3's leftovers and develop's fourth batch of questions (§516 to §553).
|
- [G-12-develop-answers-fourth](G-12-develop-answers-fourth.md): the operator's answers of 2026-11-11 noon, round 3's leftovers and develop's fourth batch of questions (§516 to §553).
|
||||||
- [G-13-review-round-3](G-13-review-round-3.md): the review of §480 to §515, rounds 2 and 3 (§600 on).
|
- [G-13-review-round-3](G-13-review-round-3.md): the review of §480 to §515, rounds 2 and 3 (§600 on).
|
||||||
- [G-14-recovery-module-and-review](G-14-recovery-module-and-review.md): the recovery module, the operator's answer of 2026-11-11 12:55 CET, and the review of §516 to §553 (§554 to §559).
|
- [G-14-recovery-module-and-review](G-14-recovery-module-and-review.md): the recovery module, the operator's answer of 2026-11-11 12:55 CET, and the review of §516 to §553 (§554 to §559).
|
||||||
|
- [G-15-develop-answers-fifth](G-15-develop-answers-fifth.md): develop's fifth batch, round 3's notes on §516 to §559, the knowledge base's review of the recovery module's record, and the operator's answers of 2026-11-11 about 14:05, 14:15 and 14:30 CET (§560 to §586).
|
||||||
|
|||||||
Reference in New Issue
Block a user