From 9381cde1b494dee45cb3e963d6ae9d919a50de9a Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 11 Nov 2026 20:16:47 +0100 Subject: [PATCH] Fix design 47 G's batches 6 and 7 by the review round, and drop every named caller list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The four reviewers' musts on §587 to §676 are written into the lines they name: the snapshot sent on its call's own session with its digest recorded, warrants matched to the current ask and its digest, the gate's copy at every start, the recovery module's hand tools as seat verbs, the catalog half's pending entries and the node-engine following no branch, the keeper following a moved finding stream, the builder's republish queue and its toolchain wait, and more. The operator's answer of about 16:10 CET ends every named caller list: every verb takes its class's default, and a module's process that calls a marked verb carries the operator's warrant for that one call (§677). Develop's D-16 to D-18 are §678 to §680, in a new part G-18 so that G-17 stays under 60 KB. Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ --- .../G-12-develop-answers-fourth.md | 2 +- .../G-14-recovery-module-and-review.md | 14 +- .../G-15-develop-answers-fifth.md | 6 +- .../G-16-develop-answers-sixth.md | 85 +++-- .../G-17-develop-answers-seventh.md | 333 ++++++++++++------ .../47-milestones/G-18-fix-round-six-seven.md | 71 ++++ .../G-4-revision-view-and-steps.md | 2 +- .../47-milestones/G-9-prepare-answers.md | 6 +- 03-DESIGN/01-to-be/47-milestones/G.md | 3 +- 9 files changed, 357 insertions(+), 165 deletions(-) create mode 100644 03-DESIGN/01-to-be/47-milestones/G-18-fix-round-six-seven.md diff --git a/03-DESIGN/01-to-be/47-milestones/G-12-develop-answers-fourth.md b/03-DESIGN/01-to-be/47-milestones/G-12-develop-answers-fourth.md index 54528f2d..9d135f14 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-12-develop-answers-fourth.md +++ b/03-DESIGN/01-to-be/47-milestones/G-12-develop-answers-fourth.md @@ -277,7 +277,7 @@ that round are written into the lines they name, here. Questions that an earlier on `wait-ended`; a `composed` whose fingerprint is not the want's is covered by that same wait or by the put's wait (§498). - **The healers' attempts.** The seat `mesh-healers` says `attempt-changed` on - `mesh.seat.mesh-healers.event.attempt-changed.`, the condition's key escaped as a key's name is (§73), + `mesh.seat.mesh-healers.event.attempt-changed..` (§665), each token escaped as a key's name is (§73), carrying the attempt's value whole as its key in `attempts` holds it and `until`, the end of that key's lifetime, or `removed: true` when the healer ends the attempt; the seat's definition, in its contracts module, keeps it last per subject, 7 days and 16 MiB (§396). The healers say it again for every open attempt at their start. The diff --git a/03-DESIGN/01-to-be/47-milestones/G-14-recovery-module-and-review.md b/03-DESIGN/01-to-be/47-milestones/G-14-recovery-module-and-review.md index 2ad4c5b9..aba7ee3b 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-14-recovery-module-and-review.md +++ b/03-DESIGN/01-to-be/47-milestones/G-14-recovery-module-and-review.md @@ -48,7 +48,7 @@ are written into the lines of G-12 they name.* restores into the live bus. The bus module's snapshot before its own `recreate` or `drop` (ADR 0595 §5, ADR 0626 §4) and the nightly dump (ADR 0626 §2) stay theirs. The restore ADR 0667 §12 tests of the snapshot `drop` takes is the recovery module's `recovery_restore` naming that snapshot, which it reads through the bus module's tool - `nats_snapshot_get` (class `read`, callers `holder:mesh-recovery@same-node` alone). + `nats_snapshot_get` (class `read`, taking its default, §610; its arguments and answer §666). - **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 *recovery module*. It runs on the node of the holder of `mesh-broker`, read from the catalog half and the seat @@ -68,21 +68,21 @@ are written into the lines of G-12 they name.* `.`, and `expiry-ended`, their fields as §560 gives them. The node agent wakes only on the ending event of its own act, and its wait for `ended` or `restored` is bounded at 90 minutes from its first ask (§405, §560), 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 - 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, + - **Who calls it.** `snapshot-kept` and `restore-kept` are of class `act` and take its default (§610, the operator's + answer of about 16:10 CET: no verb keeps a named list): the bus proves who called, every act is logged with it, + and the identity of who asked is the check (the operator, 13:06 CET); no want is read for it, since the operator, 2026-11-11 13:10 CET: "if something asks for a restore, you should do it; he'll have his reasons". `kept-points` takes the default of a read (§391). The operator, 2026-11-11 13:06 CET at lead-47's terminal: setting aside is a move, not a removal, so deleting the live objects once their aside is whole and checked (§516) needs no person's warrant, the data staying in the aside until the operator discards it; setting aside without restoring is the operator's hand tool `recovery_aside`, and discarding an aside the hand tool `recovery_discard_aside`, both of - class `act`, callers `operator` and `sessions`, written in the hand-act log first; `restore-kept` refuses + class `act`, taking its default (§610), written in the hand-act log first, each a verb of the seat (§656); `restore-kept` refuses `aside-only` and `discard-aside`, naming them (§516). The hand tools are checked by the identity of who asked: they are taken only from the operator's account as the bus proves it, and from sessions acting on it as for every `act` tool (§391), with no warrant asked per act. Each act is written in the hand-act log of the seat `mesh-hand-acts` first, with the caller the bus proved and `why`; an act whose log write fails does nothing and answers `error`, naming the log (as §480). - **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 - `act`, callers `operator` and `sessions` (§391), written in the hand-act log; they are checked by identity, as above. + `act`, taking its default (§610), written in the hand-act log, each a verb of the seat (§656); they are checked by identity, as above. §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 @@ -119,7 +119,7 @@ are written into the lines of G-12 they name.* 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, 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 only while an aside's record ends at + - **Its health.** Its declared health check names the tool `recovery_kept_points` (§657), and fails only while an aside's record ends at `removed` (§516) and no running act holds it, so a restore under way never fails it; it then also writes the 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 diff --git a/03-DESIGN/01-to-be/47-milestones/G-15-develop-answers-fifth.md b/03-DESIGN/01-to-be/47-milestones/G-15-develop-answers-fifth.md index a51a19d1..bf26d664 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-15-develop-answers-fifth.md +++ b/03-DESIGN/01-to-be/47-milestones/G-15-develop-answers-fifth.md @@ -217,7 +217,7 @@ form only. A note that corrects a line of G-12 or G-14 is written in that line; `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 + taking its default (§610), 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, @@ -515,7 +515,7 @@ form only. A note that corrects a line of G-12 or G-14 is written in that line; - **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`, + of class `read`. `indexer_unpin` (`revision`, `record`, `why`; class `act`, taking its default (§610), 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. @@ -546,7 +546,7 @@ form only. A note that corrects a line of G-12 or G-14 is written in that line; 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 + taking its default (§610), 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 diff --git a/03-DESIGN/01-to-be/47-milestones/G-16-develop-answers-sixth.md b/03-DESIGN/01-to-be/47-milestones/G-16-develop-answers-sixth.md index 6cf1618f..dcfadc5e 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-16-develop-answers-sixth.md +++ b/03-DESIGN/01-to-be/47-milestones/G-16-develop-answers-sixth.md @@ -28,8 +28,8 @@ One file of milestone G's part of [design 47](../47-delivery-from-commit-to-deli [G.md](G.md). Its design lines are numbered across every file of the part and cited as "design 47 G §n". *§587 to §594 answer develop's sixth batch (lead-47's input of 2026-11-11, met in the join and develop after §560 to -§586). Each is of internal form only, within what the records and the lines it cites decide; §588 leaves one question -to the operator, said in it. A line of another file that one of them corrects is corrected in that line (§169, §170, +§586). Each is of internal form only, within what the records and the lines it cites decide; §588 carries the operator's +answer of 2026-11-11, between 15:14 and 15:42 CET. A line of another file that one of them corrects is corrected in that line (§169, §170, §171, §177, §226, §404, §462, §513, §568, and the event table of G-4); here only what is new.* ## The ledger's upkeep calls @@ -63,42 +63,46 @@ to the operator, said in it. A line of another file that one of them corrects is ## The builder's publishes and its reads -- §588 **`builder_publish_again` publishes again every reserved version left unpublished, one module at a time.** - (§52, §369, §381; *Tools are how a module is spoken to*) The builder's tool `builder_publish_again` (class `act`, - its callers and its writing in the hand-act log as they are) takes `module` - and `version`, each optional, and `why`: - - **With both**, it publishes again that reserved version's missing artifacts, as §52 has it. - - **With `module` alone**, it publishes again each reserved version of that module whose artifacts are not all - published: at most one per `MAJOR.MINOR`, since §369 keeps one key per module and `MAJOR.MINOR` and a - superseded build's version is never released. - - **With neither**, it does so for every module whose reserved version the finding `version-unreleased` names - (§369), one module after another, the newest key first. - - **Its bound.** A publish sends the artifacts the build stored, by their digests, to the holder of the registry - seat of their kind, and builds nothing, so it takes no build capacity. An artifact no store holds is not built - by this tool: the tool names it, and its build key is built again by `builder_build_again`. The builder sends one - publish at a time to each registry seat holder, each bounded by §369's 10 minutes. The tool answers at once with - the versions it started, and each outcome is said as `package-published`, or left in `version-unreleased` with - the holder's words. - - Why: §369 gave the tool one version, and a recovery of a registry holder away for hours left many (lead-47 in the - registry recovery, issue 1966 note 206). How it is checked: whole (builder, with a fake registry holder), a holder - that refused three modules' publishes, then answers: one call with neither argument publishes the three, one at a - time, and clears their `version-unreleased`; an artifact no store holds is named and not built. - - - **By itself, on an event.** The operator, 2026-11-11 between 15:14 and 15:42 CET at lead-47's terminal, answering - this line's question, decided by the record of the builder's publish again (number to come), which extends ADR - 0673 to publishes: the builder also publishes again, by itself, every reserved version `version-unreleased` names, - on the node-engine seat's `running` of a module whose catalog graph entry claims the registry seat of the - missing artifacts' kind, on any node, and on the node-engine seat's `manifest-reads-changed` with `why` `returned` - of the node that holder runs on (ADR 0673 §2, §590); one with `why` `started` publishes nothing. On each such - event it publishes at most one version per `MAJOR.MINOR` of each module (§369's key), one publish at a time to - each holder, at most once per event heard. A publish that fails again keeps `version-unreleased` with the - holder's words and waits for the next such event. No timer. The builder's manifest `consumes` both events (it - does for ADR 0673 already). How it is checked: unit (builder), a version left unreleased is published again on - the holder's `running` and on its node's `returned`, not on `started`, once per event and one at a time; whole - (builder, a fake registry holder away and back), every unreleased version published with no hand act. +- §588 **A reserved version left unpublished is published again, by the builder on an event or by a person's tool.** + (§52, §369, §381, §590, §610, §633; ADR 0673 §2; *Tools are how a module is spoken to*) A publish sends the + artifacts the build stored, by their digests, to the holder of the registry seat of their kind, under the same + version, and builds nothing, so it takes no build capacity. + - **By itself, on an event.** The operator, 2026-11-11 between 15:14 and 15:42 CET at lead-47's terminal, decided by + the record of the builder's publish again (number to come), which extends ADR 0673 to publishes: the builder + publishes again, by itself, every reserved version `version-unreleased` names (§369), on the node-engine seat's + `running` of a module whose catalog graph entry claims the registry seat of the missing artifacts' kind, on any + node, and on the node-engine seat's `manifest-reads-changed` with `why` `returned` of the node that holder runs on + (ADR 0673 §2, §590); one with `why` `started`, or with none, publishes nothing. No timer. The builder's manifest + `consumes` both events (it does for ADR 0673 already). + - **Each event once.** The builder acts on a message of those subjects at most once, by its stream sequence: it + keeps, in its old `state` section `acted`, the last sequence it acted on per subject, so the read of §556 at its + start acts on each subject's last message only when that is newer than the kept one, and a message read again + after a restart starts nothing. + - **One queue per holder.** Each registry seat holder has one queue of versions to publish, sent one at a time, + each bounded by §369's 10 minutes; a version already queued or being published is not queued again. One event + queues at most `republish-max-versions` versions (a setting, §633, 50 unless set), at most one per `MAJOR.MINOR` + of each module (§369's key), the newest keys first; the rest wait for the next event or the tool. + - **An artifact no store holds.** It is named once in `version-unreleased` as not stored, and is not tried again on + events: its build key is built again by `builder_build_again`, which reserves anew. + - **The failure still said.** A publish that fails again keeps `version-unreleased` with the holder's words and + waits for the next such event. + - **By a person's tool.** `builder_publish_again` (class `act`, §610, written in the hand-act log) takes `module` + and `version`, each optional, and `why`: with both, that reserved version's missing artifacts (§52); with `module` + alone, each reserved version of that module whose artifacts are not all published, at most one per + `MAJOR.MINOR`; with neither, every version `version-unreleased` names, one module after another, the newest key + first. It queues as the events do and answers at once with the versions it queued; each outcome is said as + `package-published`, or left in `version-unreleased` with the holder's words. - **Before develop.** These lines rest on the record of the builder's publish again, accepted before G's builder is built from them; its number replaces "number to come" here. + + Why: the operator's answer; §369 gave the tool one version, and a recovery of a registry holder away for hours + left many (issue 1966 note 206); the queue, the sequence, the cap and the unstored artifact are the design's + (review: health and events 5, running and testing 4 and 7). How it is checked: unit (builder), a version left + unreleased is published again on the holder's `running` and on its node's `returned`, not on `started` or no + `why`, once per message: a restart reading the same last message starts nothing; a version queued is not queued + twice; one event queues at most the setting's number; an unstored artifact is named once and not tried on the next + event; whole (builder, a fake registry holder away and back), every unreleased version published with no hand act, + one at a time; one call with neither argument publishes three modules' versions. - §589 **`builder_build` answers a module's build keys whole.** (§348, §568, §575; *one-question-one-tool*) The builder's tool `builder_build` (class `read`) takes `module` and, optional, `fingerprint`. With `fingerprint`, it answers that key whole; with `module` alone, the module's build keys newest first, at most 20, each with its @@ -129,6 +133,8 @@ to the operator, said in it. A line of another file that one of them corrects is new assignment graph revision only when the capabilities answered differ from those its newest revision placed on, so a `returned` that changes nothing makes no revision. - **The builder** consumes it as ADR 0618 §4 and §568 have it, and builds a key again only on `returned`. + - **An older node-engine's event.** A `manifest-reads-changed` with no `why`, from a node-engine of before G, is + read as `started`, so it builds and publishes nothing again. Why: two events of one fact, one decided (ADR 0618 §4) and one the design's (§226), are a second source of the same fact, and ADR 0673 §2 builds on the decided one's `why` (lead-47, on ADR 0673). How it is checked: unit @@ -165,6 +171,10 @@ to the operator, said in it. A line of another file that one of them corrects is - **What was owed at the switch.** Each `owed` key the old bridge had not performed becomes an act (§169). Each `merges` key it had not performed is said once as `approval-carried` (§542) and becomes no act. The gate writes `merges` no more (§156) and reads it no more, and keeps it until §97's removal (§542). + - **A carried approval nobody uses is seen.** For each `approval-carried` it says, the gate writes the finding + `approval-carried-open` (scope the gate, id `.`, each escaped as a key's name is, §73), naming the + head the Approve named, and clears it when it hears the seat `git`'s `pull-merged` or `pull-closed` of that pull + request, which its manifest `consumes`. - **The approval.** No Approve is asked per merge (§150); an `approval` step's answer is the runner's (ADR 0666 §10, §542). @@ -173,7 +183,8 @@ to the operator, said in it. A line of another file that one of them corrects is four places (join of the gate). How it is checked: unit (gate's manifest), no `invokes` of `merge-pull` and no `consumes` of `merged` or `pushed`; the code review finds no module name of the forge bridge in the gate's code and no act `merge`; whole (gate, bridge), a merge made through `merge-pull` opens one record from `take-in.taken`, - and a `merges` key at the switch is said `approval-carried` and performed by nobody. + and a `merges` key at the switch is said `approval-carried` and performed by nobody, its `approval-carried-open` + raised and then cleared by that pull request's `pull-merged`. - §593 **The gate hears neither the teller's answers nor the view's reach.** (§150, §431, §512) The gate's reads of the teller's `answered` and the status view's `reached`, and its calls of `teller_answers` and `view_reach`, served the Approve per merge, which goes at G's delivery (§150, §431): the gate's `asks` go with it. So the gate's diff --git a/03-DESIGN/01-to-be/47-milestones/G-17-develop-answers-seventh.md b/03-DESIGN/01-to-be/47-milestones/G-17-develop-answers-seventh.md index 81aa37e9..3b40b411 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-17-develop-answers-seventh.md +++ b/03-DESIGN/01-to-be/47-milestones/G-17-develop-answers-seventh.md @@ -41,26 +41,33 @@ for several build maps is answered once, and the maps' names for it are given in ## The operator's answers -- §610 **Every class's default admits the modules that invoke it, and sessions call `warrant` and `accept`.** (§391, - §394, §405, §555; ADR 0666 §20, ADR 0286) The operator, 2026-11-11 about 15:40 CET at lead-47's terminal: "the - operator and agents may do everything, we might make it more strict and start asking for additional checks for - agent stuff, modules can get as many permissions as they want". §391's defaults become: - - `read`: `invokers`, `persons` and `sessions`, as before; - - `act`: `operator`, `sessions` and `invokers`; - - `warrant`: `operator`, `sessions` and `invokers`, and it still carries the approval mark, so each call runs only on - the operator's Approve of that one call, whoever made it (ADR 0286, which this line does not change); - - `accept`: `operator`, `sessions` and `invokers`. The runner's `accept` (§30, §394) is no longer the operator's - alone. +- §610 **No verb keeps a list of named callers: every verb takes its class's default.** (§391, §392, §394; ADR 0286; + the records this ends are named below) The operator, 2026-11-11 about 15:40 CET at lead-47's terminal: "the operator + and agents may do everything, we might make it more strict and start asking for additional checks for agent stuff, + modules can get as many permissions as they want"; and about 16:10 CET: "we can always lock it down later, but we + most definitely don't want stupid things like 'named lists'". + - **The defaults.** A verb's definition names its class, and its callers are its class's default, which the + seat-definition reader applies: `read` takes `invokers`, `persons` and `sessions`; `act`, `warrant` and `accept` + take `operator`, `sessions` and `invokers`. `invokers` is every module whose manifest names the verb in `invokes` + (§391). A module tool's callers are its class's default alike. + - **No list.** A seat definition and a manifest name no `callers`: the seat-definition reader and the manifest + validator refuse the field, naming the verb or tool, and every `callers` G's heads carry goes in G's change. So + `git`'s `tag` (§370), the build seats' `run` (§229), `node-backup`'s `now`, `restore`, `aside` and `discard-aside` + (§405, §555), `restore` taking any module's item (no own-item limit), `mesh-recovery`'s `snapshot-kept` and + `restore-kept` (§554, §659), the bus module's `nats_snapshot_get` (§554, §666), the node-engine's eleven verbs + (§393), `operator-channel`'s `ask-again` (§394), the indexer's `indexer_unpin` (§579) and every hand tool of G + take their class's default. §392's prefixed forms and `holder:@same-node` (§336) are no longer written in + a definition; a part that must tell callers apart reads the account the bus proved (`by-caller`, ADR 0259 §3). + - **What stays.** Who may publish an event or a step's result stays its owner's alone (ADR 0363 §2, ADR 0666 + §21), and a verb's own judgement of its input stays (`restore-kept` refusing `aside-only`, §516; `merge-pull` + counting a rerun only by the operator or the healers, ADR 0666 §11, §585). + - **The approval mark stays** (ADR 0286), so a `warrant` verb, or any verb a manifest marks, runs only on the + operator's Approve of that one call, whoever calls (§677). - `invokers` is every module whose manifest names the verb in `invokes` (§391). A verb whose definition names its own - `callers` keeps them (§391); §394's verbs, which take their class's default, take the new one. So `node-backup`'s - `now` and `restore` (§405, §555), which take `act`'s default, are called by the operator, sessions and every - module that invokes them: the assigner, the node agent, the bus step's grant and the recovery module, today's - callers among them [mesh-contracts DQ-6]. This amends §391 and §394. Why: the operator's answer; no accepted record - makes a `warrant` or `accept` verb the operator's alone (ADR 0286 has the operator approve each marked call and - alone answer its ask). How it is checked: unit (seat-definition reader), the table's rows for `act`, `warrant` - and `accept` give their new callers, and a verb with `callers` of its own keeps them; whole (backup holder), a - `now` from the assigner's account and a `restore` from the recovery module's are taken. + This amends §391, §392, §393 and §394, and every line naming `callers`. Why: the operator's answers. How it is + checked: unit (seat-definition reader, manifest validator), a definition or manifest naming `callers` refused, and + a table row per class giving its default; whole (backup holder, recovery module), a `restore` from a session and + from the recovery module for another module's item taken, and a `snapshot-kept` from a session taken. - §611 **Five parts move only their findings to templates in G.** (§529, §577) The operator, 2026-11-11 between 15:14 and 15:42 CET at lead-47's terminal: in G only the state `findings` and the finding stream of the teller, the status view, the watchman, enrolment and the forge bridge move to `requires` templates (§529). Their other old @@ -86,16 +93,23 @@ for several build maps is answered once, and the maps' names for it are given in `orphans` lists, removed only by the operator's `drop` (ADR 0595 §4). - `merges` and `source` stay in the old `state` section (§542, §15). - `deliveries`, `groups`, `owed` and `conditions` move to `requires` entries of the template `state`, under the same - names. At its first start, before it serves anything, the gate of G copies every key of the old section of each - into its template entry, from its own data alone, says in its journal and in `gate_records` how many keys it - copied of each, and leaves a key already in the template as it is (as §584 copies the image registry's). The old - sections' keys stay, read no more, so a revert's gate of before G finds them, until the operator's `drop`. + names. The old sections' keys stay, read no more, so a revert's gate of before G finds them, until the operator's + `drop`. + - **Copied at every start that finds the old section changed.** The gate of G keeps, in a template state of its + own `copies`, one key per state with the old section's last revision it copied and when. At each start, before it + serves anything, for each of the four whose old section's last revision is newer than that key, it copies every + key changed since: a key whose write in the old section is newer than its template key's replaces it, a key + deleted in the old section after its template key's write is deleted in the template, and an older one is left. + It then writes the mark, and says in its journal and in `gate_records` how many keys it copied and deleted of + each. So forward, a revert (whose gate of before G writes the old sections), and forward again carry every change + made while reverted, and nothing older overwrites a newer write. [mesh-catalog Q-G1.] This corrects §15's "the gate's other kept data stay in ADR 0595's templates". Why: the - operator's answer. How it is checked: unit (manifest validator), the gate's manifest of G's heads declares `merges` - and `source` old and the four templates; whole (gate), a first start with keys in the four old sections copies - them, says how many, and serves them. - + operator's answer; the copy at every start is the design's (review: security and upgrade 5, running and testing 2). + How it is checked: unit (manifest validator), the gate's manifest of G's heads declares `merges` and `source` old + and the five templates; whole (gate), forward, then a revert's write and deletion in the old sections, then + forward: the template holds the reverted gate's write, the key it deleted is gone, and a key written in the + template after the revert is kept. ## Reading the catalog half, every part alike - §614 **How a part reads the catalog half per watched branch, once for every part.** (§196, §199, §443, §459, §479, @@ -110,7 +124,11 @@ for several build maps is answered once, and the maps' names for it are given in reader of the seat: the registrations' watched branches, read by `registrations` at the start and followed by `registration-changed` (§532); before the first registrations, the branches the gate's `source` answers, read at the start and followed by the gate's `source-moved` (§507), which it stops following at the first - `registration-changed`. mesh-sdk's `go/views` adopts and drops the views (§532) and holds no seat's verb. + `registration-changed`. The gate's `source` given no branch answers `{branches}`, the branch of each + `source.` key it keeps, and given a branch that branch's source revision. mesh-sdk's `go/views` adopts and + drops the views (§532) and holds no seat's verb. The forge module, in TypeScript, follows the branches the same + way through the TypeScript form of `meshcatalogclient`, beside the seat's generated TypeScript contract in + mesh-delivery's contracts, on mesh-sdk's TypeScript view follower (§196). - **The manifest entries every such part declares.** In `consumes`: `mesh-catalog.catalog-revision`, `mesh-catalog.registration-changed` and `mesh-delivery.source-moved`. In `invokes`: `seat:mesh-catalog.revision` (with the field `none-yet`, §617), `seat:mesh-catalog.registrations`, @@ -120,13 +138,26 @@ for several build maps is answered once, and the maps' names for it are given in `running` or a `wanted` naming a fingerprint that no branch's newest revision lists and it does not hold, it asks `entry` once, as a kept call (ADR 0668 §1), and keeps the answer; it removes one when no `running` or `wanted` it holds names that fingerprint any more. The reader it passes to a pure function (§459) answers from the views and - those entries alone, and reads no bus; an entry not yet answered is answered as none, which §459 says. + those entries alone, and reads no bus. Each kept entry is `asked`, `answered` or `not-found`: + - **asked**: the reader answers it as pending, a state apart from none; the part's health says it waits on that + fingerprint, and the node-engine's have says the phase `held` with its detail opening `entry-asked:` (§421's + `entry-missing` is said only once `entry` answered not found); + - **answered**: the answer starts a new pass at once; + - **not-found**: the part writes the finding `entry-not-found` (scope the part, id the fingerprint), cleared when + nothing it holds names that fingerprint or a later ask answers it. + + `_first_views` lists these entries with their state and since when, and the part's tool + `_entry_again` (`fingerprint`; class `act`) asks one again now. - **A branch at `none yet`.** A view whose `revision` answered `none-yet` (§530) is ready and empty: the reader's answer for that branch lists no entry. - **The first pass.** A part acts on nothing until every branch it follows has its first view, `none-yet` counting as one; until then `_first_views` says each branch `waiting` and its health says it waits (§200, §556). After its first views it acts on what it holds, and a view behind is read again by §196. - - **A dropped branch.** When `go/views` drops a branch's view (§532), it clears, through the part's writer (§639), + - **The node-engine follows no branch.** It reads the catalog half only by the fingerprints its wants name + (§421), through the entries above, and declares none of the branch entries; it never waits on a branch's view, the + registrations or the gate's `source`, so it composes the gate (and every part) before any of them answers, and no + cycle runs through it at G's delivery. + - **A dropped branch.** When `go/views` drops a branch's view (§532), it clears, through the part's mesh-sdk writer (§639: a views reader writes its findings through the part's writer, never a writer of its own), every finding that view raised (`first-view-unanswered`, `view-waits`, `view-unsaid`, `view-too-large`), says the drop and each cleared finding in the part's log, and removes the view's row of `_first_views` [D-12]. @@ -136,8 +167,10 @@ for several build maps is answered once, and the maps' names for it are given in §532. Why: the same question came from five build maps, each about to build its own form (develop's D-5). How it is checked: unit (`meshcatalogclient`), a branch added by `registration-changed` and one by `source-moved` before the first registrations are followed, an entry asked once on a `running` of an unlisted fingerprint and dropped - when nothing names it, a `none-yet` branch read as empty; whole (grants part, tool runner), a part started with one - branch at `none-yet` acts once every first view is in; a dropped branch's findings are cleared. + when nothing names it, a pending entry read apart from none and a not-found one raising `entry-not-found`, a + `none-yet` branch read as empty; unit (gate), `source` with no branch lists the branches; whole (grants part, tool + runner), a part started with one branch at `none-yet` acts once every first view is in; a dropped branch's findings + are cleared; whole (node-engine), a want composed with no branch view and no `source` answered. - §615 **The tool runner's and the Go build module's manifests come from the entry too.** (§594, §614, §443, §445, test 61) The mesh MCP server of the tool runner takes each module's manifest from its catalog graph entry, through §614's reader; its first view of the indexer's `manifests` and its `consumes` of `mesh-delivery-indexer.views.manifests` @@ -145,14 +178,17 @@ for several build maps is answered once, and the maps' names for it are given in names, by `seat:mesh-catalog.entry` (§506's `manifest-digest` naming the entry's), and its `invokes` of `mesh-delivery-indexer.indexer_read_manifests` goes [mesh-catalog Q-B1]. Both join §594's readers. Why: test 61, and `manifests` is kept only for node-engines of before G (§445). How it is checked: test 61, a row each. -- §616 **The owner of the assigner's views is read from the catalog half.** (§428, §7) The tool runner's code reads the - module that holds `mesh-module-assigner` from the catalog half's claims of that seat (§614), and names the views - `.assignments` and `.seat-holders` from it, never by a name fixed in code. Its manifest's - `consumes` keeps `mesh-delivery-assigner.views.assignments` and `views.seat-holders`, the module's own declaration of - what it hears, as a manifest may name a module. Design 46 7-approval-mark §19's holder of `operator-channel` is read - from that view so found. [mesh-tools Q-R3, Q-R17.] Why: §428 removes the name from code, and the catalog half - says who claims a seat. How it is checked: unit (tool runner), a fixture catalog half naming another holder of the - seat gives views of that name; the code review finds no assigner name in the tool runner's code. +- §616 **The assigner's views are named by the seat, in the code and in the manifest.** (§428, §7) The tool runner's + code reads the module that holds `mesh-module-assigner` from the catalog half's claims of that seat (§614) and + names the views `.assignments` and `.seat-holders` from it, never by a name fixed in code. + Its manifest's `consumes` names them by the seat, `mesh-module-assigner.views.assignments` and + `mesh-module-assigner.views.seat-holders`, which the grants part resolves to the seat's holder from the catalog + half as it resolves a seat's events, so a new holder is granted with no change of the manifest. Design 46 + 7-approval-mark §19's holder of `operator-channel` is read from that view so found. [mesh-tools Q-R3, Q-R17.] Why: + §428 removes the name from code, and the catalog half says who claims a seat (review: seams and tools' note). How + it is checked: unit (tool runner), a fixture catalog half naming another holder of the seat gives views of that + name; unit (grants part), a seat-named view granted for the seat's new holder; the code review finds no assigner + name in the tool runner's code or manifest. - §617 **The long form of an `invokes` entry stands beside `*`.** (§558, §545) A manifest's `invokes` may hold `*` and long-form entries together: the tool runner's is `*`, then `{verb: "seat:mesh-catalog.revision", fields: ["none-yet"]}` and `seat:mesh-catalog.entry` with no fields named [mesh-tools Q-R4, Q-R18]. The manifest validator @@ -214,13 +250,14 @@ for several build maps is answered once, and the maps' names for it are given in its start (§205), the fingerprint the node-engine's `running` says of it; the tool runner consumes nothing more for it. Design 34 every-event §35 is corrected so. [mesh-tools Q-R14.] Why: the node-engine hands each process its own build (§205). How it is checked: unit (tool runner), the act carries the fingerprint of its environment. -- §626 **A module ends G with no more tests than it starts with.** (§419, test budget) §419 holds for the tool runner's +- §626 **A module ends G with no more tests than it starts with.** (§419, test budget) §419's count starts, for each + module, at the commit of its repository's main from which G's branch of that repository starts (its merge base with + that branch), and the check compares the module's count at G's heads against it. This holds for the tool runner's work of design 34 every-event and design 46 7-approval-mark: the new tables and the whole test of design 46 - 7-approval-mark §22 and design 34 every-event §19 replace existing tests, and every test they delete counts. - Their "New test functions are allowed within each module's budget" is corrected to say so. [mesh-tools Q-R16.] Why: - §419 is milestone G's rule and both parts ship in G's release. How it is checked: the check counts the tool runner's - tests against its count at G's start. - + 7-approval-mark §22 and design 34 every-event §19 replace existing tests, and every test they delete counts. A test + moved with its code (§655) counts in the module it moves to, as no new test there, and as deleted in the module it + left. [mesh-tools Q-R16.] Why: §419 is milestone G's rule and both parts ship in G's release. How it is checked: the + check counts each module's tests against its count at that commit. ## The node-engine and the node agent - §627 **The node-engine is a foundation part.** (§6, §529, §577; ADR 0619 §1 to §3) The node-engine composes every @@ -291,10 +328,13 @@ for several build maps is answered once, and the maps' names for it are given in (`view-waits`, `first-view-unanswered`, `view-unsaid`, `view-too-large`) are written through the part's mesh-sdk writer as kinds of their own (§580), and the writer's statement covers them beside `observe`'s. [mesh-sdk 7.] How it is checked: unit (writer), a statement keeps the reader's open findings. -- §640 **The writer keeps its copy of the finding layout, held equal to the generated types.** (§439, §452) mesh-sdk's - writer keeps its own `FindingBody`, `FindingCleared`, `FindingsStated` and `FindingsAsked`, in Go and TypeScript, and - a test in mesh-contracts holds them field for field equal to the types the seat generator emits. [mesh-sdk 8.] Why: - one layout, checked, without changing which package imports which. How it is checked: that test. +- §640 **The finding writer reads the generated types; it keeps no copy of the layout.** (§439, §452) mesh-sdk's + writer, in Go and TypeScript, defines the small interface it needs of a finding's body (its key's parts, its + `since`, its kind) and takes the types the seat generator emits for `findings` through it; it holds no + `FindingBody`, `FindingCleared`, `FindingsStated` or `FindingsAsked` of its own, so there is one layout and nothing + to keep equal. [mesh-sdk 8.] Why: a copy held equal by a test in another repository is not checked on a change of + mesh-sdk alone, and the TypeScript copy by none (review: running and testing 6). How it is checked: unit (writer, + both languages), a generated body written and stated; the code review finds no copy. - §641 **A stream kept last per subject: where it is read and how it is told.** (§396, §556) mesh-sdk's `HearSeatEvents` makes §556's read at the start with an ordered consumer, then follows the durable, and names the stream `waiting` in `_first_views` until the read ends [mesh-sdk 9]. The grants part tells such a stream by @@ -341,79 +381,134 @@ for several build maps is answered once, and the maps' names for it are given in ## mesh-catalog's parts -- §654 **The readers of the forge module's old events and tools move to the seat `git`.** (§310, §311, §313, §431) - mesh-config consumes `git`'s `pull-merged` and `pull-closed` in place of `gitea.pull.merged`, `gitea.pull.closed` - and `gitea.forge.pull-request.closed`, and invokes `seat:git.pull` in place of `gitea.gitea_get_pull_request`; the - records module consumes `git.pull-merged`; mesh-issues invokes `seat:git.pull` and `seat:git.contains`, and reads a - pull request's checks and reviews from the delivery record's `show` (its steps' results, the review step's among - them), in place of `seat:mesh-delivery.checks` and `gitea_pull_reviews`. [mesh-catalog Q-F1.] How it is checked: - unit (manifest validator), each manifest of G's heads names none of the old events or tools. +- §654 **The readers of the forge module's old events and tools move to the seat `git`.** (§310, §311, §313, §431; + ADR 0659 §1) [mesh-catalog Q-F1.] + - **mesh-config** consumes `git`'s `pull-merged` and `pull-closed` in place of `gitea.pull.merged`, + `gitea.pull.closed` and `gitea.forge.pull-request.closed`, and invokes `seat:git.pull` in place of + `gitea.gitea_get_pull_request`; **the records module** consumes `git.pull-merged`. + - **The order.** Main's forge module says its own `pull.merged`, not the seat's events, so each consumer of + `git.pull-merged` or `pull-closed` is ordered after the forge module's version that says them, by the edge of kind + 6 its `consumes` gives (§558); its durable consumer is made from the stream's first message, so no merge said + before it began is missed, and no catch-up through `git.pull` is needed. + - **mesh-issues** invokes `seat:git.pull` and `seat:git.contains`, and reads a pull request's steps from the + runner's `show` given the repository and the pull request's head commit (`seat:mesh-pipeline-runner.show` in its + `invokes`), which answers that commit's pipelines with each step's result, the review step's among them (ADR + 0666 §22); a commit with no pipeline is answered `none`, which mesh-issues shows as "no run". The forge's own + reviews are read nowhere: G keeps no review record (ADR 0659 §1). Its read of `seat:mesh-delivery.checks` and + `gitea_pull_reviews` go. + + How it is checked: unit (manifest validator), each manifest of G's heads names none of the old events or tools; + unit (mesh-config, records), each acts on a `git.pull-merged` fixture; unit (mesh-issues), a commit with no + pipeline shown as "no run". - §655 **The take and restore of one stream is shared code in mesh-sdk.** (§554, §464; ADR 0672 §1) The code that takes and restores one stream's snapshot moves whole from the bus module's `bussnap` into mesh-sdk's `go/bussnap`, - imported by the bus module (its snapshot before `recreate` and `drop`) and by the recovery module (its points and - restores); no module imports another module's package. [mesh-catalog Q-R1.] Why: code two modules share lives in + imported by the bus module (its snapshot before `recreate` and `drop`), by the recovery module (its points and + restores), and by any part that takes the nightly dump's stream snapshots; no module imports another module's + package, and no third copy is kept. The edge of kind 1 from mesh-sdk's package (§47) orders its publication before + the bus module's and the recovery module's builds. [mesh-catalog Q-R1.] Why: code two modules share lives in mesh-sdk (§464's reason). How it is checked: the code review finds one copy. -- §656 **The hand tools are the recovery module's own tools, answered by its process.** (§554, §566; ADR 0672 §3, §7) - Each hand tool is a module tool on the process's own `by-caller` subject, the bundle passing the call through, so - the bus proves the tool runner's account; the seat `mesh-recovery` gains no verb. [mesh-catalog Q-R2.] How it is - checked: whole (recovery module), a hand tool from another account is refused by the bus. -- §657 **The recovery module's health check is a tool.** (§554, §468) The recovery module serves the read tool - `recovery_kept_points`, answering what `kept-points` answers, and its declared health check names it. - [mesh-catalog Q-R3.] How it is checked: unit (manifest validator), the check names a served tool. +- §656 **The hand tools' acts are verbs of the seat `mesh-recovery`.** (§554, §566; ADR 0672 §7) Each hand tool's act + is a verb of the seat `mesh-recovery`, `by-caller`, answered by the process: `take`, `restore`, `retry`, `aside`, + `discard-aside`, `restore-aside`, `cancel` and `expire-points`, each of class `act` (§610), beside `snapshot-kept`, + `restore-kept` and `kept-points`, all defined in mesh-contracts. The tools bundle's `recovery_*` tools call them, + named in its `invokes`, and hold no grant of their own; the bus proves the tool runner's account, as ADR 0672 §7 + has the bundle call the seat's verbs. [mesh-catalog Q-R2.] Why: ADR 0672 §7 (review: seams and tools 2). How it is + checked: unit (mesh-recovery's contract), each verb read; whole (recovery module), each hand tool acts through its + verb. +- §657 **The recovery module's health check is a tool.** (§554, §468, §561) The recovery module serves the read tool + `recovery_kept_points`, answering what `kept-points` answers, its bundle naming `seat:mesh-recovery.kept-points` in + `invokes`, and its declared health check names it. The check fails while an aside's record ends at `removed` and no + running act holds it, as §554 has it, which `recovery_kept_points` answers. §554's "calls `kept-points`" is + corrected so. [mesh-catalog Q-R3.] How it is checked: unit (manifest validator), the check names a served tool; + whole (recovery module), an unrestored aside fails the check. - §658 **A module new in G starts with the tests its lines name.** (§419) A module new in G counts from none: its tests are the checks its design lines name (for the recovery module, its one whole test and the unit rows of its lines), within the per-module budget. [mesh-catalog Q-R4.] ## mesh-contracts' seat contracts -- §659 **`snapshot-kept` and `restore-kept` are of class `act`.** (§554; ADR 0672 §3) Class `act`, their callers - `seat:node-engine` alone, as §554 names them. [mesh-contracts DQ-5.] +- §659 **`snapshot-kept` and `restore-kept` are of class `act`.** (§554, §610) Class `act`, taking its default, as + every verb does (§610). [mesh-contracts DQ-5.] - §660 **A finding's key and value.** (§461, §437, §439) The state `findings` keeps the key `..` and the value `#/bodies/Finding`. [mesh-contracts DQ-7.] - §661 **`list` shows the caps.** (§547) The seat `mesh-broker`'s `list` answer gains `caps {sum-mib, account-limit-mib, server-limit-mib}`, an absent limit meaning unlimited. [mesh-contracts DQ-10.] - §662 **A subject function with parts can fail.** (§523) A generated subject function with `` tokens answers `(string, error)` in Go and throws in TypeScript for an empty part, `.` or `..`. [mesh-contracts DQ-11.] -- §663 **The condition keeper's sources are the bus module's `created` events.** (§515, §529) The keeper takes a - source when it hears the seat `mesh-broker`'s `created` of a part's `finding-events` entry, and a foundation part's - old finding stream from the catalog half (§614); at its start it reads both by `list` and the catalog half. §515 is - corrected so. [mesh-contracts DQ-12; D-7's COND9.] Why: the grants part makes the consumers (§386), and no binding - names one. How it is checked: whole (keeper, bus module), a part declaring finding events is asked once its entry - is `created`. +- §663 **The condition keeper's sources are the bus module's `created` events, and it follows a moved stream.** (§515, + §529, §611, §612) The keeper takes a source when it hears the seat `mesh-broker`'s `created` of a part's + `finding-events` entry, named in its `consumes`, and a foundation part's old finding stream from the catalog half + (§614); at its start it reads both by `list` and the catalog half. When a part's catalog graph entry no longer + declares the stream the keeper follows for it (its findings moved to a template, §611, or to an old section, §612), + the keeper drops that source and its consumer, keeps the part's open conditions, and asks `findings-asked` on the + new stream once it is a source; the part's statement there settles them (§384). §515 is corrected so. + [mesh-contracts DQ-12; D-7's COND9.] Why: the grants part makes the consumers (§386), and no binding names one; a + moved stream must neither raise twice nor leave a condition open (review: health and events 1). How it is + checked: whole (keeper, bus module), a part declaring finding events is asked once its entry is `created`; a part + whose findings move keeps its condition raised once and clears it from the new stream. - §664 **`backed-up` needs no contract change.** (§563) The backup holder's answer carries a put-off item's `act` and since when in its own fields. [mesh-contracts DQ-14.] -- §665 **`attempt-changed` is keyed by condition and attempt.** (§541) The subject is - `mesh.seat.mesh-healers.event.attempt-changed..`, kept last per subject, so two attempts on one - condition both stay. [mesh-contracts DQ-15.] How it is checked: unit (healers' contract). - +- §665 **`attempt-changed` is keyed by condition and attempt.** (§541, §73) The subject is + `mesh.seat.mesh-healers.event.attempt-changed..`, each token escaped as a key's name is (§73), + kept last per subject, 7 days and 16 MiB (§541), so two attempts on one condition both stay. At about 0.5 KiB a + message, 16 MiB holds about 30,000 attempts, far more than seven days have seen (an estimate). The stream discards + nothing new: a publish past its cap fails, and the healers say it in their health and write the finding + `attempt-unsaid` (scope the healers, id the condition), cleared by that subject's next publish taken. §541's + subject is corrected so. [mesh-contracts DQ-15.] How it is checked: unit (healers' contract), two attempts of one + condition kept; whole (healers), a full stream raises `attempt-unsaid`. ## Met in develop -- §666 **`nats_snapshot_get`'s arguments and answer.** (§554, §567; ADR 0672 §1, §8; ADR 0666 §16) It takes `request`, - the id of the bus module's `drop` or `recreate` request whose snapshot is asked, as the keeper's requests record it. - It answers `{request, module, local, stream, size, digest, at, object}`: `digest` the `sha256:` digest of the - snapshot's bytes, and `object` the name of the snapshot in the bus module's sent store (§59), which the recovery - module reads by the standing grant of that answer; a snapshot larger than the sent store's cap (§591) answers - `error`, naming its size and the cap. `recovery_restore` names it by `request`, and the recovery module checks the - bytes against `digest` before it takes any aside, as §567. [D-1.] Why: the snapshot crosses the bus as every large - answer does, never as a shared file. How it is checked: whole (bus module, recovery module), a `drop`'s snapshot - restored by `recovery_restore` with its `request`, and one with altered bytes refused. -- §667 **Where a trusted change and the seed wait for their warrant.** (§3, §8; ADR 0666 §2, §12; ADR 0259) [D-2, D-3.] +- §666 **`nats_snapshot_get`: the snapshot recorded with its digest, and sent on the call's own session.** (§554, + §567, §518, §620; ADR 0672 §1, §8; ADR 0667 §12) [D-1.] + - **When it is taken.** The bus module's keeper, taking the snapshot before a `drop` or `recreate` (ADR 0595 §5), + writes into that request's record in its state `requests` the snapshot's `path` (under its snapshots directory), + `size` and `digest` (`sha256:` of its bytes) before it touches the live data. A snapshot it cannot write whole and + record so makes the `drop` or `recreate` refuse, naming why, before anything is removed. + - **Who deletes it.** The keeper alone: the snapshot file and its record are kept 90 days (ADR 0667 §12, as the + delivery records), its setting `snapshot-keep-days`, and removed at the keeper's start and at each new request + once older, each removal written in its journal. + - **The call.** It takes `request`, the request's id. It reads the file, computes its digest, and answers `error` + `snapshot damaged`, naming the request, when it differs from the recorded one, or `snapshot missing` when no file + is there. Otherwise it answers `{request, module, local, stream, size, digest, at, chunked: true}` and sends the + file on the call's own get session, `.get.`, in chunks under the bus's + per-message limit, each acknowledged by the caller before the next, as §518 and §620 have a get session; only the + bus module's account publishes the chunks and only the caller's account answers them, granted so (§489). No size + limit applies and nothing goes through the sent store. + - **Its use.** `recovery_restore` names it by `request`, and the recovery module checks the bytes it received + against `digest` before it takes any aside (§567). + + Why: a snapshot larger than the sent store's cap, or asked after its 7 days, could never be restored, and the + sent store's read grant is wider than this one caller (review: all four domains). How it is checked: whole (bus + module, recovery module, with small settings), a snapshot larger than 256 MiB restored whole; one asked eight days + after its `drop` with `snapshot-keep-days` 90 restored; a file altered on disk after the `drop` refused `snapshot + damaged`; a `drop` whose snapshot cannot be written refuses before it removes anything. +- §667 **Where a trusted change and the seed wait for their warrant.** (§3, §8; ADR 0666 §2, §12; ADR 0259 §6; ADR + 0286 §10) [D-2, D-3.] - **Kept.** The indexer keeps each change of `register`, `policy`, `watch` and `unwatch` awaiting its warrant in its old `state` section `proposals`, one key `.` (`..` for `watch` and - `unwatch`, each token escaped as a key's name is, §73), holding the change whole, the ask's id, its caller and - when it was asked; the seed's key is `seed`. Capped at 4 MiB. + `unwatch`, each token escaped as a key's name is, §73), holding the change whole, its `digest` (`sha256:` of the + change in RFC 8785's canonical form), the current ask's id, its caller and when it was asked; the seed's key is + `seed`. Capped at 4 MiB. - **Asked.** Through `operatorchannelclient`, kind `ask`, level `approve`, its `about` the key, so a newer change of - the same key replaces the open ask (ADR 0666 §12). - - **Heard.** By the indexer's durable consumer of `mesh.seat.operator-channel.event.decided.`. - A warrant writes the version by compare-and-set and deletes the key; a Decline, an expiry or a refusal deletes it - and writes nothing, said in its journal and its answer to the caller; the seed's keeps `seed-waits` (§8). - - **A restart.** At its start the indexer reads each key and the seat `operator-channel`'s `asks` for its ask: - a decided one is applied as above, an open one waited on, and one the router no longer holds deleted, said. - - **Its tools.** `indexer_proposals` (class `read`) lists the keys with their asks; `indexer_seed_again` raises - the seed's ask again from its key (§8). + the same key replaces the open ask (ADR 0666 §12); the ask names every value the change moves (§3) and carries the + change's `digest`, so the warrant approves those exact values (ADR 0286 §10). + - **Heard.** The indexer's manifest `consumes` `operator-channel.decided`, on + `mesh.seat.operator-channel.event.decided.`, through a durable consumer. A warrant is + applied only when its ask's id is the key's current ask and its digest the key's: it writes the version by + compare-and-set and ends the key `applied`. A warrant of a replaced ask writes nothing, said in its journal. A + Decline, an expiry or a refusal ends the key with that outcome; the seed's keeps `seed-waits` (§8). + - **Ended keys stay readable.** An ended key keeps its outcome, its ask and when, until the next change of the same + key replaces it. + - **A restart.** At its start the indexer reads each open key and the seat `operator-channel`'s `asks` for its + ask: a decided one is applied or ended as above, an open one waited on, and one the router no longer holds ended + `lost`, said. + - **Its tools.** `indexer_proposals` (class `read`) lists the open and ended keys with their asks and outcomes; + `indexer_proposal_drop` (`key`, `why`; class `act`, in the hand-act log) cancels the key's open ask and ends it + `dropped`; `indexer_seed_again` raises the seed's ask again from its key (§8). - How it is checked: whole (indexer), a `policy` applied on its warrant after a restart while open, a decline - writes nothing, and two `policy` changes of one module leave one ask. + How it is checked: whole (indexer), a `policy` applied on its warrant after a restart while open; a decline ends + the key `declined`, read by `indexer_proposals`; two `policy` changes of one module leave one ask, and the first + ask's late warrant writes nothing; a dropped key's ask is cancelled. - §668 **`manifest-accepted`'s `problems`.** (§500; ADR 0579 §1) The event gains `problems`, a list of `{rule, words}`: each problem the indexer's re-judgement finds in a manifest it keeps accepted because its digest is unchanged (ADR 0579 §1), the same items its verdict writes as warnings; an empty list when none. It is defined in @@ -438,16 +533,25 @@ for several build maps is answered once, and the maps' names for it are given in §526 gives the want's field; every artifact of the build is kept on that node, and each artifact in `made` keeps its digest as now. A build not kept carries no `kept-on`. [D-9.] How it is checked: unit (builder), a kept build's `build.ended` names its node, and the assigner writes it into the want (§526). -- §672 **The builder's toolchain wait.** (§267, §276, §472, §629) The builder holds an entry while its fingerprint - names a toolchain version of its language other than the one the builder's newest `toolchain-agreed` of that - language names (§267). It keeps each wait in its old `state` section `waits`, one key `.` - (escaped as a key's name is, §73), capped at 4 MiB, deleted when the wait ends. It says `wait-held` and - `wait-ended` on its own stream, on `mesh.stream.mesh-delivery-builder.event.wait-held` and `.wait-ended` (G-4's - table), the body the fields of §629's wait with `step` `building`, `on` `toolchain:@`, `module` - and `fingerprint`, and `wait-ended` its `how` (`ran` when a `toolchain-agreed` names that version, `released` by - `builder_release`). `builder_waits` reads the state, and `builder_release` builds the entry with the running build - module, written in the hand-act log (§276). [D-10.] How it is checked: whole (builder), an entry held until - `toolchain-agreed` names its version, then built, the wait ended `ran`; one released by hand ended `released`. +- §672 **The builder's toolchain wait.** (§267, §276, §472, §557, §629, §633) The builder holds an entry while its + fingerprint names a toolchain version of its language other than the one the builder's newest `toolchain-agreed` + of that language names (§267). + - **Its state.** Each wait is kept in the builder's old `state` section `waits`, one key `.` + (each token escaped as a key's name is, §73), capped at 4 MiB, deleted when the wait ends. + - **Its events.** It says `wait-held` and `wait-ended` on its own old `streams` section `waits`, on + `mesh.stream.mesh-delivery-builder.event.wait-held..` and `.wait-ended..`, + kept last per subject, 7 days, 16 MiB; the body the fields of §629's wait with `step` `building`, `on` + `toolchain:@`, `module` and `fingerprint`, and `wait-ended` its `how` (`ran` when a + `toolchain-agreed` names that version, `released` by `builder_release`). At its start it says `wait-held` again + for every key of `waits`. G-4's table reads so. + - **Its bound.** 60 minutes, its setting `toolchain-wait-minutes`; past it the builder writes the finding + `toolchain-waits` (scope the builder, id `.`), cleared when the wait ends. + - **Its tools.** `builder_waits` reads the state, and `builder_release` builds the entry with the running build + module, written in the hand-act log (§276). + + [D-10.] How it is checked: whole (builder, with small settings), an entry held until `toolchain-agreed` names its + version, then built and ended `ran`; one released by hand ended `released`; one past its bound raises + `toolchain-waits`; a restart says the open wait again. - §673 **`package-published`'s one `dependencies` list holds both kinds.** (§374, §466) The contract's `dependencies` in each artifact of `package-published` is §466's `resolved` and `toolchain` in one list: each item `{kind, part, version, digest}`, kind 1 for each `resolved` package (its part the package's artifact reference, §504) and @@ -476,10 +580,15 @@ for several build maps is answered once, and the maps' names for it are given in `.` whose want or running build names it, written by compare-and-set, capped at 4 MiB. An entry object is removed only at the first revision after no kept revision lists it and its `named` set is empty; a `wanted` or `running` that moves on removes its `.` from the old fingerprint's set. - - **Its tool.** `indexer_entries` (class `read`) reads a fingerprint's key, its object's digest and its `named` set. + - **A node that leaves.** A `running` stays on its stream for ever, so a member a `running` put in the set leaves it + also when the want of that node and module is removed (`wanted` saying it removed: the node left or the module was + unplaced), whatever that node last said running. + - **Its tools.** `indexer_entries` (class `read`) reads a fingerprint's key, its object's digest and its `named` set; + `indexer_named_drop` (`fingerprint`, `member`, `why`; class `act`, in the hand-act log) removes one member. How it is checked: unit (indexer), an entry no revision lists is answered by `entry` while a want names it and - removed after the want moves on; a restart reads `named` whole before it removes anything. + removed after the want moves on; a member whose want is removed leaves the set; `indexer_named_drop` removes one; + a restart reads `named` whole before it removes anything. - §676 **Each entry carries its artifacts' package names.** (§491, §478, §504, §412) At take-in the indexer reads each artifact's package name from the revision's own files at the artifact's path (the `module` of its `go.mod` for a Go package, the `name` of its `package.json` for an npm package, the manifest's image name for an image) and writes it diff --git a/03-DESIGN/01-to-be/47-milestones/G-18-fix-round-six-seven.md b/03-DESIGN/01-to-be/47-milestones/G-18-fix-round-six-seven.md new file mode 100644 index 00000000..2be6e4cb --- /dev/null +++ b/03-DESIGN/01-to-be/47-milestones/G-18-fix-round-six-seven.md @@ -0,0 +1,71 @@ +--- +layer: to-be +status: in-progress +design: 47 +milestone: G +updated: 2026-11-11 +decisions: + - "ADR 0673" + - "ADR 0672" + - "ADR 0668" + - "ADR 0667" + - "ADR 0666" + - "ADR 0660" + - "ADR 0656" + - "ADR 0626" + - "ADR 0619" + - "ADR 0618" + - "ADR 0596" + - "ADR 0595" + - "ADR 0579" + - "ADR 0573" + - "ADR 0448" + - "ADR 0429" + - "ADR 0363" + - "ADR 0286" + - "ADR 0283" + - "ADR 0259" +--- + +# 47, milestone G: the fix round of batches 6 and 7 + +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". + +*§677 to §680 come from the fix round of the review by architectural domain of §587 to §676 (lead-47's input of +2026-11-11): the approval mark once no verb names its callers (the operator's answer of about 16:10 CET, §610), and +develop's D-16 to D-18, of internal form only. The round's other fixes are written in the lines they correct.* + +## The approval mark, with no named callers + +- §677 **A module's process that calls a marked verb carries the operator's warrant for that one call.** (§610; ADR + 0286, ADR 0259 §6, ADR 0626 §4) A call through the tool runner is asked, judged and claimed by the tool runner as + ADR 0286 and design 46 7-approval-mark have it. A module's process may now call a marked verb directly (§610); then: + - **The caller asks.** It makes the act of that call as ADR 0286 §10 and §11 make one (the address, the node that + serves it, the build and every argument, digested with `ActDigest`), asks it through `operatorchannelclient` + under its own module's name, at level `approve`, and calls only once the warrant is given, naming the ask in the + call. + - **The holder checks.** The marked verb's holder takes the call only with a warrant whose act's digest is the + digest of the call it received, claims it once (`Take`), and refuses any other call before acting, naming the + ask the caller must make, as the bus module's keeper checks a warrant (ADR 0626 §4). mesh-sdk's seat server does + this for every marked verb, read from the definition's or the manifest's mark, so no holder builds it. + + Why: the mark stays while no caller list does (O-6; review: security and upgrade 2). How it is checked: whole + (a fixture marked verb, its holder and a module's process), a call with no warrant refused, one with a warrant for + other arguments refused, one with its warrant run once, and the same warrant used twice refused. + +## Develop's D-16 to D-18 + +- §678 **The forms of a finding's `owner` and `waiting-on`.** (§451, §540, §580) Each is one of three forms, written as + patterns in the finding layout's definition: a session `^[a-z0-9][a-z0-9._-]*@[a-z0-9][a-z0-9-]*$` (who@node), a seat's + name `^[a-z][a-z0-9-]*$`, or a commit's author `^forge:[A-Za-z0-9._-]+$`. mesh-sdk's finding writer (§580) refuses any + other, naming the field; the contract's fixtures read each form. [D-16.] How it is checked: unit (writer), each form + written and another refused. +- §679 **`reserved`'s answers.** (§582, §586) `reserved` answers `{module, version, artifacts, released}`, `released` a + boolean (as §530's `none-yet`), or `{error}`, a string; `module`, `version` and `artifacts` are required only without + `error`. [D-17.] How it is checked: unit (`mesh-builds`' contract), the three answers read. +- §680 **Where the seat generator and the build modules' conformance kit live.** (§464, §495) §495's "the seat + generator is imported by no running module" reads "by no running module but through `steprun`'s regenerate and + compare". The build modules' shared conformance kit is `sdk/steprun/conformance` in the delivery SDK, which + mesh-catalog's build modules and their checks import. [D-18.] How it is checked: the code review. + diff --git a/03-DESIGN/01-to-be/47-milestones/G-4-revision-view-and-steps.md b/03-DESIGN/01-to-be/47-milestones/G-4-revision-view-and-steps.md index d76a980a..96d9b947 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-4-revision-view-and-steps.md +++ b/03-DESIGN/01-to-be/47-milestones/G-4-revision-view-and-steps.md @@ -285,7 +285,7 @@ say another runs a build (ADR 0363 §2); the gate's events are granted to the ga | an entry wanted | `wanted` | `mesh-wants`, the assigner | `mesh.seat.mesh-wants.event.wanted` | the seat's definition in `mesh-delivery-contracts` (ADR 0641 §2) | | an entry composed, and running healthy | `composed`, `running` | `node-engine`, the node-engine on each node | `mesh.seat.node-engine.event.composed.`, `.running..`, the latter on a stream kept last per subject with no age limit | the seat's definition in `mesh-contracts` | | a node's capabilities changed, or its node returned | `manifest-reads-changed` (ADR 0618 §4; §590) | `node-engine`, the node-engine on that node | `mesh.seat.node-engine.event.manifest-reads-changed.` | the same | -| a wait held, and ended | `wait-held` (step, acting part, its version, the entry, since when, its bound), `wait-ended` (the same, and how: ran, released) | each holder: `mesh-wants` for the assigner (placing, wanting and composing), `mesh-grants` for the grants part, the builder's own stream | `mesh.seat..event.wait-held`, `.wait-ended`; `mesh.stream.mesh-delivery-builder.event.wait-held`, `.wait-ended` | each seat's definition; the builder's manifest | +| a wait held, and ended | `wait-held` (step, acting part, its version, the entry, since when, its bound), `wait-ended` (the same, and how: ran, released) | each holder: `mesh-wants` for the assigner (placing, wanting and composing), `mesh-grants` for the grants part, the builder's own stream | `mesh.seat..event.wait-held`, `.wait-ended`; `mesh.stream.mesh-delivery-builder.event.wait-held..`, `.wait-ended..` (§672) | each seat's definition; the builder's manifest | | a store filling, full, and back below its cap | `filling`, `full`, `room` | `mesh-catalog`, `mesh-wants`, `mesh-delivery` | `mesh.seat..event.filling`, `.full`, `.room` | each seat's definition | | a record pins or frees a revision; a candidate's heads replaced; a record ended | `pinned`, `freed`, `heads-replaced`, `record-ended` | `mesh-delivery`, the gate | `mesh.seat.mesh-delivery.event.` | the seat's definition in `mesh-delivery-contracts` | | a milestone's ask asked, withdrawn and answered, until G's delivery | `milestone-asked`, `milestone-withdrawn`, `milestone-answered` | `mesh-delivery`, the gate | `mesh.seat.mesh-delivery.event.`, the milestone in the event, on the seat's family stream, apart from each delivery's `transition` | the same | diff --git a/03-DESIGN/01-to-be/47-milestones/G-9-prepare-answers.md b/03-DESIGN/01-to-be/47-milestones/G-9-prepare-answers.md index 87e387d0..b16132b6 100644 --- a/03-DESIGN/01-to-be/47-milestones/G-9-prepare-answers.md +++ b/03-DESIGN/01-to-be/47-milestones/G-9-prepare-answers.md @@ -60,10 +60,10 @@ line says so.* from the node-engine's code: the definition is the one source (§68). Why: the design's choice (Q-H8). How it is checked: unit (definition reader), each of the eleven names its callers; the code review finds no callers table in the node-engine. - §394 **The callers of G's new trusted acts.** (§482) `mesh-catalog`'s `register`, `policy`, `watch` and `unwatch`, and - `mesh-delivery`'s `recovery`, are of class `act`: the operator and sessions; `registrations` is a `read`. + `mesh-delivery`'s `recovery`, are of class `act`, taking its default (§610: the operator, sessions and invokers); `registrations` is a `read`. `mesh-pipeline-runner`'s `review` is called by sessions, refusing none for authorship in G (§482); its `accept` by - its class's default (§610), which amends §30's "a person". `operator-channel`'s `ask-again` is a seat verb, its callers the - operator and the healers (§83, §40). Why: the operator, 2026-11-11 02:56 CET on Telegram, "As proposed" (S4, S10, + its class's default (§610), which amends §30's "a person". `operator-channel`'s `ask-again` is a seat verb of class `act`, taking its + default (§610), the healers among its invokers (§83, §40). Why: the operator, 2026-11-11 02:56 CET on Telegram, "As proposed" (S4, S10, C18, D2, D3, D4). How it is checked: whole (indexer, runner, operator-channel), a call from any other caller is refused by the bus; unit (definition reader), each verb's class and callers. - §395 **An accepted kind naming no callers keeps today's grant.** `operator-channel`'s kinds `ask` and `condition` diff --git a/03-DESIGN/01-to-be/47-milestones/G.md b/03-DESIGN/01-to-be/47-milestones/G.md index 2a3166b4..6196aca2 100644 --- a/03-DESIGN/01-to-be/47-milestones/G.md +++ b/03-DESIGN/01-to-be/47-milestones/G.md @@ -82,7 +82,7 @@ file on 2026-11-10, and is cited as "design 47 G §n". A sentence that holds a d stayed in the main file, and G builds what it says from G's delivery. A section named in italics is in this part, or, when it is not here, in the main file. -The part is seventeen files, each read whole, its design lines numbered across them: +The part is eighteen files, each read whole, its design lines numbered across them: - [G-1-pipelines-registration-and-steps](G-1-pipelines-registration-and-steps.md): pipelines per module: registration, watched branches, steps and policy, what holds a delivery, approval, groups, dependencies, a publish. - [G-2-pipelines-sizes-checks-and-tools](G-2-pipelines-sizes-checks-and-tools.md): pipelines per module: any size, the pipeline makes the check, who may say what, health, recovery, tools, kept data, how G itself is delivered, the choices under ADR 0666 and ADR 0667. @@ -101,5 +101,6 @@ The part is seventeen files, each read whole, its design lines numbered across t - [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). - [G-16-develop-answers-sixth](G-16-develop-answers-sixth.md): develop's sixth batch: the ledger's upkeep calls, the builder's publishes again and its read of a module's builds, one event of a node's capabilities, the object stores' caps, the gate's merge path from G's delivery, and the readers of a module's manifest (§587 to §594). - [G-17-develop-answers-seventh](G-17-develop-answers-seventh.md): develop's seventh batch: the operator's answers of 2026-11-11 15:14 to 15:42 CET (callers by class, the five parts' findings, the forge and image registry's other entries, the gate's kept data), how every part reads the catalog half per watched branch, and the refreshed build maps' questions (§610 to §676). +- [G-18-fix-round-six-seven](G-18-fix-round-six-seven.md): the fix round of §587 to §676: the approval mark once no verb names its callers, and develop's D-16 to D-18 (§677 to §680). Design 34's milestone [every-event](../34-milestones/every-event.md) and design 46's milestone [7-approval-mark](../46-milestones/7-approval-mark.md) ship in milestone G's release, built in its repositories beside G's lines (lead-47, 2026-11-11 15:30 CET); where one of their lines and a line of G differ, G's later line holds and the other is corrected in place (§624 to §626).