From d49dccb8d583496cb897fef64e18e4b6bea5d0f0 Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 23 Oct 2026 16:10:08 +0200 Subject: [PATCH] Use the glossary's word composition check where the merge gate was struck (issue 1303) --- .../01-to-be/30-the-mesh-updates-itself-on-a-push.md | 4 ++-- .../01-to-be/45-a-core-that-cannot-fail-silently.md | 8 ++++---- .../01-to-be/47-delivery-from-commit-to-delivered.md | 10 +++++----- .../01-to-be/48-a-module-says-how-it-is-healthy.md | 2 +- .../01-to-be/57-building-config-and-provisioning.md | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/03-DESIGN/01-to-be/30-the-mesh-updates-itself-on-a-push.md b/03-DESIGN/01-to-be/30-the-mesh-updates-itself-on-a-push.md index 1259365b..4b7d95e6 100644 --- a/03-DESIGN/01-to-be/30-the-mesh-updates-itself-on-a-push.md +++ b/03-DESIGN/01-to-be/30-the-mesh-updates-itself-on-a-push.md @@ -15,7 +15,7 @@ decisions: # 30 — The mesh updates itself on a push -**Where it stands, 2026-10-17** (the records cleanup, issue 1072; playbook 07, "The design's state is written back"). Built on main: mesh-controller's delivery plans, composing check and merge window (plan.go, release_plan.go, merge_gate.go, merge_window_bus.go, changeplan.go, with their migrations), which design 47 builds on. Not yet checked against this text nor given an as-is: issue 1075. +**Where it stands, 2026-10-17** (the records cleanup, issue 1072; playbook 07, "The design's state is written back"). Built on main: mesh-controller's delivery plans, composition check and merge window (plan.go, release_plan.go, merge_gate.go, merge_window_bus.go, changeplan.go, with their migrations), which design 47 builds on. Not yet checked against this text nor given an as-is: issue 1075. **Today the mesh does not update itself; a person drives the pipeline by hand, and one class of change freezes it.** A code change lands in `mesh-controller` or `mesh-catalog`, and getting it onto @@ -168,7 +168,7 @@ Revision, ADR 0238 it — the module's own directory, the whole repository for a module built from its root, a repository a recipe names — and a file no build reads, at the root or in a directory holding no module, rebuilds nothing. One function maps a changed file onto modules and one answers what a merge moves and builds; -the merge handler, the what-if, the composing check and a pull request's check ask them. Only a commit on the +the merge handler, the what-if, the composition check and a pull request's check ask them. Only a commit on the module's trunk is registered. ## What a push does not send (2026-10-05) diff --git a/03-DESIGN/01-to-be/45-a-core-that-cannot-fail-silently.md b/03-DESIGN/01-to-be/45-a-core-that-cannot-fail-silently.md index 62d1c142..d29d9b64 100644 --- a/03-DESIGN/01-to-be/45-a-core-that-cannot-fail-silently.md +++ b/03-DESIGN/01-to-be/45-a-core-that-cannot-fail-silently.md @@ -69,7 +69,7 @@ calls, the hand-act log, the facts snapshot), **`mesh-host`** (the node-engine: order, epoch refusal, the `report` verb, rollback witnessing), **mesh-tools** (the tool runner and the mesh MCP server: their heartbeat, passing every argument, health answers), **mesh-catalog** (the `operator-channel` seat's holder and channels, the watcher, the providers' retirement, the catalogue's -composing check), **mesh-sdk** (the TypeScript providers' loop and its retirement), **mesh-lab** (the +composition check), **mesh-sdk** (the TypeScript providers' loop and its retirement), **mesh-lab** (the replays and the induced-failure scenarios). --- @@ -320,7 +320,7 @@ producer that wrote it. | Probe | Asserts | From | |---|---|---| -| D1 | every machine's declaration composes, and passes the node-engine's validation (the validator is a package of `mesh-host` the controller and the composing check import — one validator) | 236, 263 | +| D1 | every machine's declaration composes, and passes the node-engine's validation (the validator is a package of `mesh-host` the controller and the composition check import — one validator) | 236, 263 | | D2 | every holder of the mesh's resolver answers a machine name for IPv4, and NODATA for IPv6 | 262 | | D3 | every seat on record has a live holder that answers (`holder-silent`, H3) | 208, 218 | | D4 | every kept archive is held by a manifest | 253 | @@ -685,7 +685,7 @@ the bus server, the store and the node-engine. No secret and no address: an addr from a documentation range. It is kept in the artifact store as `facts/latest`, where the build seat reads it. -**The composing check.** In mesh-controller, `mesh-host` and mesh-catalog, a check composes every machine of +**The composition check.** In mesh-controller, `mesh-host` and mesh-catalog, a check composes every machine of the snapshot with the change applied and runs the node-engine's validator over each. A change that makes any machine fail to compose or validate fails its check, naming the machine's role and the module. The resolver module's tests run under both C libraries the snapshot lists. A test in each core @@ -921,7 +921,7 @@ the verdict as their status, and `merge-check.sh`; in `mesh-host` `merge-check.s installer's user list; in mesh-lab the replays of 262 and 266, the register and the prover; in hq the replay rule in `cycle.py`. The prover ran the replays of **236, 262, 263, 266 and 273: each fails on the commit before its fix** (236's check did not exist there) **and passes on it**. **Not yet:** R4, R5 and the -rest of the window's incidents as replays; the composing check's first runs against the live mesh's snapshot; +rest of the window's incidents as replays; the composition check's first runs against the live mesh's snapshot; the status required to merge, which is the operator's setting on the forge; mesh-tools' and mesh-sdk's `merge-check.sh`. 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 d6697dec..686ecbed 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 @@ -427,7 +427,7 @@ From its delivery, a check is this: mesh-sdk version it composed with, and while the assigner and the controller run different versions the controller's self-check raises a condition until they agree. No judge is built from a change: a change to the composition is proved by its own tests, a field only a newer composition reads goes out as optional first, and - the running composition refuses a manifest that uses a field it does not read, naming the field. What it fails on, and its warning past twelve rebuilt modules, are the composition check's, as they were the controller's composing check's (ADR 0446, ADR 0237 §2). + the running composition refuses a manifest that uses a field it does not read, naming the field. What it fails on, and its warning past twelve rebuilt modules, are the composition check's, as they were the controller's composition check's (ADR 0446, ADR 0237 §2). The assigner writes the verdict under the checker's hash of the heads it judged, in its own bucket, and the checker reads it into the composition of its verdict, which says "not run" until the assigner's module exists (ADR 0528 §5). @@ -779,8 +779,8 @@ development, the check's share about a minute): group's merges (ADR 0418 §1, §5, §6). - The controller's tables of builds, build requests, rollouts and their tiers, batches and merges, and assignments; the record mirrors, probe D17's audit and healer H6 for those kinds (ADR 0408). -- At release 4's deliveries (R4f for the composing check, the judge and the two statuses; R4g for the scripts): `merge-check.sh` and its `# mesh-check-toolchain` line in every repository a module is - built from, hq's included once the delivery is done (ADR 0445 §6, ADR 0527 §3); the controller's composing check, composing every +- At release 4's deliveries (R4f for the composition check, the judge and the two statuses; R4g for the scripts): `merge-check.sh` and its `# mesh-check-toolchain` line in every repository a module is + built from, hq's included once the delivery is done (ADR 0445 §6, ADR 0527 §3); the controller's composition check, composing every machine from clones and throwaway stores (ADR 0446 §1, §6); the judge built from a change and the Go build module's second account for it (ADR 0446 §5); and the two statuses `mesh/merge-gate` and `mesh/repo-check` (ADR 0447 §1, ADR 0527 §2). @@ -819,7 +819,7 @@ release reports the controller's code lines against research 063's baseline (acc | R2c | The controller says when it last heard each machine from presence alone, and no longer hears the alive message | 14 | mesh-controller | 1183 (every reader of last heard takes presence; the controller's alive side deleted) | | R2d | The node-engine sends no alive message | 14 | the node-engine (`mesh-host`) | 1158 (the node-engine's alive side deleted) | | R3a | The gate, the bridge, the indexer and the teller can read one layout of the source revision, candidates, modules, merges, asks, answers, owed acts, forge messages and conditions, and one function computes the source fingerprint: mesh-sdk ships them before their users (ADR 0437) | — (15 needs it) | mesh-sdk | 1200 (source revision, candidates, modules, forge messages), 1201 (merges, asks, owed acts, answers), 1202 (a condition on its one subject), 1203 (the source fingerprint, proven against three fingerprints the live builder recorded); ahead of it in mesh-controller, so those could be read: 1204 and 1208 (`builds` says each build's source fingerprint) | -| R3b | The controller finds the delivery seat's holder by its claim and records each build's fingerprint inputs; the router takes conditions on their one subject; the operator sees no change (ADR 0437) | — | mesh-controller, mesh-catalog (messenger) | 1210 (the controller's own path and the composing check's rule by the seat's claim), 1211 (a merge's announcement heard from the seat's holder), 1212 (the pull requests' keys read from the holder's bucket), 1213 (a merge's warrant read under the asker the announcement names: the teller, or mesh-delivery until R3d), 1214 (the builder computes the source fingerprint with mesh-sdk's function), 1215 (a build record carries its fingerprint's inputs), 1216 (a module may say a condition only under its own name, proven on the controller's grant); in the messenger: 1217 (the router takes a condition on its one subject), 1218 (the same over the bus); one delivery group. Its prepare step found that the controller hears no `transition` or `group` event, and that the router cannot refuse a condition under another module's name, the grant does: both go into R3c's insight on ADR 0437 with 1209 | +| R3b | The controller finds the delivery seat's holder by its claim and records each build's fingerprint inputs; the router takes conditions on their one subject; the operator sees no change (ADR 0437) | — | mesh-controller, mesh-catalog (messenger) | 1210 (the controller's own path and the composition check's rule by the seat's claim), 1211 (a merge's announcement heard from the seat's holder), 1212 (the pull requests' keys read from the holder's bucket), 1213 (a merge's warrant read under the asker the announcement names: the teller, or mesh-delivery until R3d), 1214 (the builder computes the source fingerprint with mesh-sdk's function), 1215 (a build record carries its fingerprint's inputs), 1216 (a module may say a condition only under its own name, proven on the controller's grant); in the messenger: 1217 (the router takes a condition on its one subject), 1218 (the same over the bus); one delivery group. Its prepare step found that the controller hears no `transition` or `group` event, and that the router cannot refuse a condition under another module's name, the grant does: both go into R3c's insight on ADR 0437 with 1209 | | R3c | The forge bridge, the indexer and the teller run beside today's mesh-delivery and write their keys; the view shows modules against the controller's source fingerprints; nothing is merged by them yet (ADR 0437) | 15 in part | mesh-delivery (forge bridge, indexer, teller, view), mesh-catalog (the forge module) | 1235 (the forge bridge writes pull messages on FORGE), 1236 (its merged message, with the trees of the merge commit), 1237 (its messages for the pull requests open at its start and each reconnect), 1238 (the indexer writes the candidate groups), 1239 (the indexer writes the modules' fingerprints at a trunk merge, and 1209: none for an image that compiles a Go program from a context), 1240 (the teller runs and carries nothing yet), 1241 (the view shows the candidate groups and each module's fingerprint against the controller's); in the forge module: 1234 (a merge commit's trees in one call, and the head branch in the open pull requests); one delivery group, mesh-catalog first. Its prepare step found three orders: the forge had no tool for a commit's trees, so the forge module joins the milestone as a member of its group; and mesh-sdk shipped two layouts before it, the controller's build record (1223) and a build's directory and a pull request's module directories (1233). It also found that the bridge's FORGE is a stream the others hear by `consumes`, not a bucket they `read`; that the broker test of the three credentials goes into R3d with the gate's (1243); and that the parts hand-write their bus connection until mesh-sdk gives one (1242): facts for ADR 0437's next insight, with R3d's | | R3d | The gate's keys can carry what the forge needs and the controller answers a what-if as data, so the gate has what it reads before it runs; a failed delivery plan asks the operator Retry on the phone, and a seat whose holder is assigned nowhere passes to its only claimant; the operator sees only the Retry notice (ADR 0450, ADR 0449) | — | mesh-sdk, mesh-controller | in mesh-sdk: 1321 (a merge key carries the Approve's heads), 1322 (an owed act carries a status's target, a commit without a pull request, two comments), 1323 (a name a key cannot hold is escaped); in mesh-controller: 1324 (what-if as data), 1325 (the build seat reads the gate's pull keys), 1326 (the gate's buckets writable by its runner only), 1243 (the three parts' credentials); and, delivered first as feature no-terminal (ADR 0449): 1317 (the seat passes to its only claimant), 1314 (a failed delivery plan raises a condition), 1315 (Retry offered and performed), 1316 (a refused answer is told). Its prepare step found four things the gate reads that ship before it, which cut the former R3d in two (ADR 0450), and two steps on the path that needed the operator's terminal (ADR 0449) | | R3e | A group reaches the mesh as one source revision written by the gate; the merge's Approve is asked by the teller and answered on the phone until issue 953; the view shows the open asks; today's module mesh-delivery is carried over into the gate when it first holds the seat and ends; no step needs the operator's terminal (ADR 0437, ADR 0450) | 15 | mesh-delivery (gate's parts: forge bridge, teller, indexer, view), mesh-catalog (the gate, mesh-delivery removed, mesh-issues), mesh-tools (the tool runner's waits) | opened when it is prepared, from R3d's survey; the controller's deletions it makes possible go to release 4 (1318) | @@ -828,7 +828,7 @@ release reports the controller's code lines against research 063's baseline (acc | R4c | The new parts run dark beside today's: the indexer writes the manifests by digest and the fingerprints in the new form beside today's (its own, first delivery), then the build modules (the Go build module, the Node and TypeScript build module: toolchain, sandbox, fetch, digest, test, build), the builder, the checker writing `mesh/check` as a status the forge does not require, and the assigner's composition check writing into the checker's report; the build seat's accounts are decided by a record before the build modules' pull requests are opened (ADR 0453 clauses 4, 6, 7, 8, 11, 12, 16; ADR 0465 §4); the builder is ADR 0478's. It is delivered in ADR 0465 §5's order: mesh-sdk's layouts; the forge bridge and the indexer with the controller's facts in format 2; the build modules; the builder; the checker; the bus user list's composer moved into mesh-sdk; the assigner's composition check; the fetch and run steps. The build modules each run as an account of their own with a forge key known read-only on one forge user (ADR 0466); each builds with the node's installed toolchain at the agreed version and does not refuse on a node with another (ADR 0477, issue 1572), answers a long step with its id and finishes it on a key, is called on a named machine, and runs on the four nodes that run the build agent today (ADR 0469) | 22, 23 (measured on the dark run, proved in R4f) | mesh-delivery (indexer, builder, checker, assigner's composition check), mesh-catalog (build modules, ssh-client, gitea), mesh-controller (the build agent's whole-check tests, the script's steps as tests), mesh-sdk | 971 (its record first), 1297 (the assigner's composition check), 1309 (the fetch and run steps), 1287, 1288, 1289, 1290, 1291, 1292 (the checker; the build modules run the tests), 1251; the steps of 1293 and 1294 that are no test become tests in R4c to R4e; the rest opened when it is prepared | | R4d | Four modules stop being built from a Dockerfile: route-proxy, nats, n8n and mail's autoconfiguration module (automx, replaced by a Go program), each rework its own release step, nats in a delivery of its own; free between R4a and R4e and never in the same delivery as another release (ADR 0452, ADR 0453 clauses 13, 14, 16) | — | mesh-catalog, mesh-controller (route-proxy), the node-engine (`mesh-host`: n8n's supplementary group) | the four image reworks, opened when it is prepared | | R4e | The controller asks no build: a build is keyed by its fingerprint, the new form becomes the only one as one group, and a merge builds nothing its check built; builders fetch over SSH, so an SDK change ships with its users; the vendored copies leave mesh-controller and mesh-sdk; delivered only once the builder's artifact digests equal build-agent's (ADR 0453 clauses 2, 4, 5, 6) | 16, 2, 4 in part | mesh-controller (builds are no longer asked), mesh-delivery (builder), mesh-sdk | 979 (the installed toolchains; closed with the toolchain images in R4g), 1304, the controller asking no build (opened when it is prepared) | -| R4f | A pull request carries one required status that says what it proved and how long each part took; the controller's composing check and its replays are deleted with the two old statuses; the controller's deletions R3e makes possible go; each level's times are measured, and a bound fails a repository from the first check that meets it (ADR 0447, ADR 0450 §8, ADR 0453 clauses 4, 9, 10) | 21, 22, 23, 24 (the status; the scripts' absence is proved in R4g) | mesh-delivery (checker, assigner), mesh-controller (composing check, replays, `delivery-plan`, `forget-checks`, the asker `mesh-delivery` deleted), mesh-catalog (gitea) | 1299 (the composing check deleted; closes issue 709, the replays' socket), 1300, 1301, 1302 (one status), 1305 (ADR 0482 §8), 1318 | +| R4f | A pull request carries one required status that says what it proved and how long each part took; the controller's composition check and its replays are deleted with the two old statuses; the controller's deletions R3e makes possible go; each level's times are measured, and a bound fails a repository from the first check that meets it (ADR 0447, ADR 0450 §8, ADR 0453 clauses 4, 9, 10) | 21, 22, 23, 24 (the status; the scripts' absence is proved in R4g) | mesh-delivery (checker, assigner), mesh-controller (composition check, replays, `delivery-plan`, `forget-checks`, the asker `mesh-delivery` deleted), mesh-catalog (gitea) | 1299 (the composition check deleted; closes issue 709, the replays' socket), 1300, 1301, 1302 (one status), 1305 (ADR 0482 §8), 1318 | | R4g | The last milestone of release 4 and release 5 as one, with one switch-over and no rehearsal (ADR 0524 §1): builds and checks are asks on streams that each build node pulls when it has a free slot, deliveries first, with nothing holding checks and no controller queue (ADR 0525); the assigner is made with its composition check, writes each node's wants compared with what the controller sends and every difference, and the view answers the asks that need no proof of who answered (ADR 0528, ADR 0437 §10); no module's fingerprint takes the builder (ADR 0530); the scripts of the repositories a module is built from, build-agent with its socket and Dockerfile code, the toolchain images and the controller's build code go, and the builder delivers its own module, the build modules and the controller from its keys (ADR 0453 clauses 5, 8, 10; ADR 0524 §5, §7); the ways to deliver without the builder are recorded (ADR 0526); hq's four checks are Go tests (ADR 0527); each repository's script goes (ADR 0529); the word for the composition check's predecessor is struck. Its pull requests are opened only after five readings, the revert path read, not shown on a test merge (ADR 0524 §3) | 4 (from R4g mesh-build-image, rootless, is the only part that builds an image: ADR 0487 §7), 17, 24 (no `merge-check.sh` in a repository a module is built from) | mesh-sdk, mesh-controller (build-agent removed), mesh-delivery, mesh-catalog, mesh-tools, mesh-tools-go, the node-engine (`mesh-host`), mesh-media-catalog, okioki, hq | 1887 (the flow), 1297 (the assigner), 1295 (`merge-check.sh` goes), 979 (closed with the toolchain images), 1296 and 1303 (hq's check, the old word struck), 1299, 1305, 1294, 1318 (the controller's deletions) | | R6 | Each node applies from its wants, a new version reaches the module's canary first and the rest once it is healthy there, and the plans are deleted from the code | 18, 19 | the node-engine (`mesh-host`: the node agent), mesh-controller (plans deleted), mesh-delivery (the gate's delivery states go) | opened when it is prepared | diff --git a/03-DESIGN/01-to-be/48-a-module-says-how-it-is-healthy.md b/03-DESIGN/01-to-be/48-a-module-says-how-it-is-healthy.md index 791ab877..6291a130 100644 --- a/03-DESIGN/01-to-be/48-a-module-says-how-it-is-healthy.md +++ b/03-DESIGN/01-to-be/48-a-module-says-how-it-is-healthy.md @@ -448,7 +448,7 @@ open: composes the field — the endpoint as the port the machine published it on, the defaults written out — only for a machine whose newest statement says so, and strips it for an older engine, which parses strictly and would refuse the whole declaration. So the engine rolls out first, then the controller, and the - catalogue declares only once that controller runs: until then the composing check refuses a declaration, which + catalogue declares only once that controller runs: until then the composition check refuses a declaration, which is the protection working. - **The engine's looks.** http and tcp from the machine to the published port; a redirect is an answer and is not followed; a certificate is not judged. A unit's readiness is read from the show liveness already diff --git a/03-DESIGN/01-to-be/57-building-config-and-provisioning.md b/03-DESIGN/01-to-be/57-building-config-and-provisioning.md index 73b5c8b2..b252b3c8 100644 --- a/03-DESIGN/01-to-be/57-building-config-and-provisioning.md +++ b/03-DESIGN/01-to-be/57-building-config-and-provisioning.md @@ -151,15 +151,15 @@ glossary says it is the older word. **Proof:** `words.py` passes. stage.* A file resource takes `"template": "files/"` in place of `content`; the module's build packs `files/` into an archive artifact of its own (the existing `archive` packing); registration and `Resolve` read each template's text back from the packed tree into `content`, so composition and the node-engine -are unchanged; `module check` and the composing check read templates from the repository tree beside the +are unchanged; `module check` and the composition check read templates from the repository tree beside the manifest; a file naming both `template` and `content` is refused. **Proof:** composition tests: a module -with its text in `files/` composes byte-identically to the same module with it inline; the composing check +with its text in `files/` composes byte-identically to the same module with it inline; the composition check judges a change to a template alone. **T2 (issue 655) — The twelve modules with copies.** *mesh-catalog. A day.* adwaita, clipmenu, dunst, feh, gnome-keyring, i3, i3status-rust, lemurs, picom, rofi, screen-lock and xdg move to their templates; the 34 inline copies and the `sameAsSource` tests go. **Proof:** each module's composed declaration on its -nodes is unchanged (the composing check's plan says no file changes). +nodes is unchanged (the composition check's plan says no file changes). **T3 (issue 656) — The desktop modules.** *mesh-catalog. A day.* Every remaining module assigned only to workstations. **Proof:** as T2.