diff --git a/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md b/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md index 295414cd..5378124c 100644 --- a/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md +++ b/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md @@ -4,6 +4,7 @@ status: in-progress code: [mesh-controller, mesh-catalog modules/mesh-delivery-gate, mesh-catalog modules/gitea, mesh-delivery, mesh-host, mesh-sdk, mesh-vault, mesh-contracts, hq 00-META/checks] updated: 2026-11-09 decisions: + - "ADR 0663" - "ADR 0661" - "ADR 0660" - "ADR 0659" @@ -786,17 +787,20 @@ Findings 11). How each is kept, read and retained is this design's choice under (a gap in the revisions it heard) asks `revision` once more, said in its log (ADR 0615 §5). The design's choice under ADR 0656 §6: one form of the fact, never `modules` kept beside the catalog graph for these readers, which would be a second source of the same fact. How it is checked: test 61. - - **The forge module's tools come from mesh-sdk's TypeScript side.** mesh-sdk's TypeScript side serves the proved - caller, a verb's `callers`, a seat's publish, and a view's read and ask-again tools, so the forge module, reading - through the seat's TypeScript contract, answers `_first_views` and `_first_view_again` as the Go - parts do from `go/views`, with no follower or tool of its own. + - **The forge module's tools come from mesh-sdk's TypeScript side.** mesh-sdk's TypeScript side has no view + today; milestone G adds there a view follower with its read and ask-again tools, beside the proved caller, a + verb's `callers` and a seat's publish, so the forge module, reading through the seat's TypeScript contract, + answers `_first_views` and `_first_view_again` as the Go parts do from `go/views`, with no + follower or tool of its own. Its cost: a release of the TypeScript side rebuilds every TypeScript module, which + the delivery carries like any change of a package its users build in. - **The order is the module graph's, and the foundation's own rule where the graph has no edge.** Six of the readers declare the verb in their `invokes`, so the served-verb edge delivers none of them to any node before a build serving `revision` runs (ADR 0615 §2, ADR 0614). Two are left out of the graph's order (ADR 0614 §3, ADR 0615 §2): the tool runner, a foundation part, and the forge module, on a cycle with the indexer, which reads the forge through the seat `git`. For both the order is carried by ADR 0615 §4 and §6: the owner answers at once from what it holds, and a reader started before it waits, saying so. The tool runner asks `revision` of the indexer's - own runtime, never through itself, the tool's `callers` list naming it (ADR 0615 §3, ADR 0621 §1, §2); the forge + own runtime, never through itself, the tool's `callers` list naming it (ADR 0663, which changes ADR 0621 §1, §2 and + ADR 0615 §3; proposed, to be accepted before G's push); the forge module answers the indexer's reads through the seat `git` before it has a first view of its own, so neither waits on the other. - **With no view, a reader waits; it never reads "no modules".** All eight follow *A part with no view says it @@ -982,7 +986,7 @@ say another runs a build (ADR 0363 §2); the gate's events are granted to the ga | Step | Event | Owner: the seat, then the module | Subject | Declared in | |---|---|---|---|---| -| a catalog graph revision kept | `catalog-revision` | `mesh-catalog`, the indexer | `mesh.seat.mesh-catalog.event.catalog-revision` | the seat's definition in `mesh-delivery-contracts` | +| a catalog graph revision kept, saying whether it is a trunk revision or a candidate's | `catalog-revision` | `mesh-catalog`, the indexer | `mesh.seat.mesh-catalog.event.catalog-revision` | the seat's definition in `mesh-delivery-contracts` | | an assignment graph revision kept | `assignment-revision` | `mesh-wants`, the assigner | `mesh.seat.mesh-wants.event.assignment-revision` | the seat's definition in `mesh-delivery-contracts` (ADR 0641 §2) | | a difference worked out | `difference` | `mesh-wants`, the assigner | `mesh.seat.mesh-wants.event.difference` | the same | | an entry taken in | `take-in.taken`, which gains the entries | the indexer's own | `mesh.stream.mesh-delivery-indexer.event.take-in.taken` | the indexer's manifest | @@ -1009,7 +1013,7 @@ on another node's subject is refused by the bus. | Line | The assigner | The indexer | |---|---|---| -| read everything it holds | `assigner_revision` (one assignment graph revision whole, with the revisions of its inputs), `assigner_revisions` (every kept revision with what pins it, and the store's fill against its cap), `assigner_entry` (one entry, with the seat rule that gave each edge), `assigner_difference` (a change's difference), `assigner_waits` (*Order without a person*), `assigner_candidate_graphs` (every candidate's graphs: its heads, its revisions, since when), `assigner_consumer` (its consumer of the gate's events: the last applied, the waiting), `assigner_puts` (each put with its step, since when, the `running` that ended it, and whether it stands: past its 30 minutes or older than the trunk's newest build) | `indexer_catalog_revision` (one catalog graph revision), `indexer_catalog_revisions` (every kept revision with what pins it, and the store's fill against its cap), `indexer_candidate_graphs` (every candidate's catalog half), `indexer_consumer` (the same as the assigner's) | +| read everything it holds | `assigner_revision` (one assignment graph revision whole, with the revisions of its inputs), `assigner_revisions` (every kept revision with what pins it, and the store's fill against its cap), `assigner_entry` (one entry, with the seat rule that gave each edge), `assigner_difference` (a change's difference), `assigner_waits` (*Order without a person*), `assigner_candidate_graphs` (every candidate's graphs: its heads, its revisions, since when), `assigner_consumer` (its consumer of the gate's events: the last applied, the waiting), `assigner_puts` (each put with its step, since when, held or not, the `running` that ended it, and for a put without hold whether it is past its 30-minute bound; a put older than the trunk's newest build of its module said so) | `indexer_catalog_revision` (one catalog graph revision), `indexer_catalog_revisions` (every kept revision with what pins it, and the store's fill against its cap), `indexer_candidate_graphs` (every candidate's catalog half), `indexer_consumer` (the same as the assigner's) | | do by hand what it does itself | `assigner_recompute` (compute a revision again from its named inputs and compare it with the one kept) | `indexer_recompute` (compute a catalog graph revision again from its source revision and compare it with the one kept) | | recover without help | `assigner_drop_candidate_graph` (drop a candidate's graphs whose gate event never came), `assigner_release` (*Order without a person*) | `indexer_drop_candidate_graph` (the same for its half) | | one seat, many tools | `mesh-wants`: `revision`, `entry`, `difference` | `mesh-catalog`: `revision`, beside `seat-definitions` | @@ -1330,7 +1334,9 @@ the gate no longer watches the checker's verdicts for a hold. **Its record is to 0548 §2 to §4, §9 and §10, ADR 0551 and ADR 0534 §4's judgement of `mesh/check` by the merge are in force, and ADR 0661, which ends the first two and changes the third (proposed, needs the operator's Approve), is to be accepted before milestone G's pull requests are pushed; until it is accepted, the rule below holds as those records have it. ADR 0662 -is withdrawn; G builds ADR 0661. How it is checked: in the gate's whole-module test an approved merge into a +is withdrawn; G builds ADR 0661. Beside it, ADR 0663 (proposed: the indexer answers `revision` in its own runtime to +exactly the parts that invoke it, the tool runner among them) is to be accepted before the push too, since the tool +runner's first view of the catalog half rests on it (*Every other reader of which modules exist*). How it is checked: in the gate's whole-module test an approved merge into a repository under a running check is handed at once, and the gate's manifest declares no `turns` and no setting `check-gates-merge`; in the checker's, a check claims at once with no gate state granted to read. @@ -2084,23 +2090,31 @@ later change of a kept data's form, not as a case of this milestone. pins a want by being forgotten, as a session's puts of a node-engine build did for seven hours on 2026-11-09 (issue 1966), and milestone G's one logged put of its own indexer ends by itself. - **Until milestone G, from the have; from G, from `running`.** The issue 1966 recovery ends the put by the read of - the node's have the assigner already makes, and keeps that end until G. In G the end moves to the node-engine - seat's `running..` naming the put's fingerprint, which milestone G gives that event, heard through a - durable consumer of the assigner's own declared in its `consumes`, the one its composing waits hear too - (*Composing waits per node*); from then it never reads the node's have across the seam (ADR 0596 §2). The order is - an edge of the module graph: the node-engine that says `running` with its fingerprint before the assigner that - ends a put on it. + the node's have the assigner already makes, and keeps that end until G. That read crosses the seam against ADR + 0596 §2, kept on purpose until G, because no `running` event carries a fingerprint before G. In G the end moves + to the node-engine seat's `running..` naming the put's fingerprint, which milestone G gives that + event, heard through a durable consumer of the assigner's own declared in its `consumes`, the one its composing + waits hear too (*Composing waits per node*); from then it never reads the node's have. A `running` without a + fingerprint, as a node-engine from before G says it, ends no put: a put on a node whose node-engine is from before + G ends on the first `running` with a fingerprint from that node's new node-engine, which the composing waits move + first on that node, and `put-stands` says it meanwhile. - **Ended at once when the node already runs it.** At the put's ask, and at the assigner's start for every put not ended (one written before the upgrade among them), a put ends at once when the last `running` the assigner holds for that node and module names its fingerprint; a put of the running build pins nothing. A `running` naming another fingerprint ends nothing. - - **The end is its own step.** The put's end is the step `ended`, written on its key and said as the assigner's - event `put`, carrying the fingerprint and the `running` that ended it (or the release that did). - - **A put that stands is said.** A put not ended 30 minutes after its want was written, or one older than the - trunk's newest build of its module, is said by `assigner_puts` and as the finding `put-stands`, naming the node, - the module and the fingerprint, which the condition keeper raises (ADR 0564 §2); it clears when the put ends. - Thirty minutes is many times a module's start window and the canary's wait, so a put moving normally raises - nothing. How it is checked: test 62. + - **The end is a step the put already has.** The put ends with its existing step `done`, or `released` when a + release ends it, written on its key and said as the assigner's event `put`, carrying the fingerprint and the + `running` that ended it. No new step is added, so a reverted assigner, which knows `done`, `released` and + `refused` as ended, never reads an ended put as running. + - **A put without hold that stands is said, by the watchman.** When a put without hold has its want written, the + assigner says `wait-held` on the seat `mesh-wants` for it (node, module, fingerprint, since when) with a bound of + 30 minutes, and `wait-ended` when it ends. The watchman times it as it times every wait, and past the bound writes + the finding `put-stands`, naming the node, the module and the fingerprint, which the condition keeper raises + (ADR 0564 §2) and clears on `wait-ended`; at its own start the watchman seeds its open puts from `assigner_puts`, + as it seeds `acting-part-late`, so a put whose assigner stopped after writing its want is still timed. Thirty + minutes is many times a module's start window and the canary's wait, so a put moving normally raises nothing. A + held put is listed by `assigner_puts` as held, with since when, and raises nothing: holding is what it was asked + for. `assigner_puts` also lists a put older than the trunk's newest build of its module. How it is checked: test 62. - **The bus module is wanted like any module; only a warranted want replaces its server** (ADR 0594, changing ADR 0539 §14 and §15, ADR 0546 §8 and ADR 0565 §7 for the bus module). The assigner writes the bus module's want by the same rules as every module's, and the node agent applies what that want brings (its files, its processes' bus @@ -2713,18 +2727,22 @@ What milestone G's prepare found, and its test: names the module (in `meshcatalogclient`'s test and the forge module's); a candidate's `catalog-revision` changes nothing in any reader, and the forge module grants no write before its first view nor from a candidate; the tool runner started before the indexer says it waits, takes no empty view as no modules, raises `view-waits` after five - minutes, and once it has its first view keeps answering while the indexer is stopped (each module's existing tests, - a row each; whole, tool runner; live, a search of the catalog's and mesh-tools' code and manifests finds no + minutes, and once it has its first view keeps answering while the indexer is stopped; the forge module answers + `_first_views` with the revision it holds and the one it waits for (each module's existing tests, a row + each; whole, tool runner and forge module; live, a search of the catalog's and mesh-tools' code and manifests finds no `indexer_read_modules` and no view `modules`, and after milestone G's first merge that adds a module the status view's `view_reach` and the watchman's manifest findings name it, as the operator sees them). 62. **A put without hold ends itself.** A put with `hold` false of a fingerprint the node does not run yet ends on that - node's `running` naming its fingerprint, at the step `ended` with the fingerprint and that `running`, and the next - pass of the rules writes the want, so a later build is wanted with no `assigner_release`; a `running` of another - fingerprint ends nothing; a put of the build the node already runs ends at its ask; a put written before the + node's `running` naming its fingerprint, at the step `done` carrying the fingerprint and that `running`, and the + next pass of the rules writes the want, so a later build is wanted with no `assigner_release`; a `running` of + another fingerprint ends nothing; a `running` without a fingerprint ends no put, and the node's new node-engine's + `running` with one ends it; a put of the build the node already runs ends at its ask; a put written before the assigner's start, whose node already runs it, ends at that start; a put whose `running` was said while the - assigner was stopped ends after its restart; a put not ended within 30 minutes, and one older than the trunk's - newest build, is listed as standing by `assigner_puts` and raises `put-stands`, which clears when it ends; - `assigner_release` ends a put without hold; a held put stays until released (whole, assigner; live, + assigner was stopped ends after its restart; a reverted assigner reads the ended put as ended; a put without hold + not ended 30 minutes after its want says `wait-held` and the watchman raises `put-stands`, which clears on its + `wait-ended`, and with the assigner stopped after the want is written `put-stands` is still raised; a held put + past 30 minutes raises nothing and is listed by `assigner_puts` as held with since when; `assigner_release` ends a + put without hold at the step `released`; a held put stays until released (whole, assigner and watchman; live, `assigner_puts` after milestone G's put of its own indexer). ## What retires @@ -3016,7 +3034,7 @@ and what answers it: | tools | no fill read; the repair tool's path; the indexer's hand tool; the data set aside at a restore | fill in each read tool; `gate_record_repair` names each owner's verb; `indexer_recompute`; `backed-up` lists it and `discard-aside` removes it | | running qualities | storage that grows without limit; the build module's wait ended two ways; a checking program built per check; the wait clocks; a revert whose assigner starts before its indexer catches up | 90-day records, unpinned revisions removed, entries stored once, caps with `filling`, `full` and `room`; the agreed toolchain; one build per fingerprint; clocks from the build's end, composing per node; the ordering edges of a revert | | testing | a revert test that needed a second check; the view with the assigner down | whole-module revert tests on the real builds from before milestone G; the assigner stopped and a cold control-node | -| health and events | waits with no event or bound; a record that never ends; parts waiting for the view unreported; when a wait is first said | `wait-held` at the start with its bound, timed by the watchman; held and failed outcomes and `record-ended`; `view-waits` after five minutes | +| health and events | waits with no event or bound; a record that never ends; parts waiting for the view unreported; when a wait is first said; a put that never ends | `wait-held` at the start with its bound, timed by the watchman; held and failed outcomes and `record-ended`; `view-waits` after five minutes; `put-stands`, timed by the watchman from the put's `wait-held` | | security | a checking program hiding a removed rule; forged events; the `run` ask's grant; a kept build overwritten by the program it built; the review line retired before the review verb's grant | the running checker names every change of the checking program's fingerprint; the node in event subjects and grants per account; builds kept only from a step that runs nothing; the review verb left to issue 1782 | | upgrade | a newer indexer never wanted after milestone G; a revert across a change of kept data's form | the stand-in catalog graph revision; restore points taken before a move across a `form` change, restored at a revert before the reverted build starts, the node-engine back last |