Graduate research 058 into design 47's release 4: a check runs only what changed, its tests by the language's build module, its composition by the assigner, in one status
mesh/merge-gate head 9ffa60924ee9 merged into trunk c6d36b2f32c3 — pass: the change touches no module of the mesh's graph
mesh/repo-check head 9ffa60924ee9 merged into trunk c6d36b2f32c3 — pass: its merge-check.sh passed
mesh/delivery delivered

The check took 3 to 4.5 minutes on every change and paid the whole suite again on every re-ask; the operator's target leaves it about a minute. ADRs 0444 to 0447 decide how; the glossary gains composition check and kept verdict, and merge gate is struck once release 4 is delivered (issue 1303).
This commit is contained in:
2026-10-19 22:03:44 +02:00
parent c6d36b2f32
commit 9ffa60924e
2 changed files with 94 additions and 12 deletions
+18 -8
View File
@@ -403,14 +403,23 @@ and the operator act. **Recorded by** the controller's `identity` and `licences`
back when it fails. The domain is continuous integration and delivery, named **delivery**, and its parts live in
the repository `mesh-delivery` (ADR 0429 §2). **Recorded by** the `mesh-delivery` module (deliveries) and the
controller (the planner, the rollout) until release 6 of ADR 0429; from each release on, by the parts it builds. **Downstream of** Module, Core, Health and repair and Data.
**Decided by** ADR 0162, 0218, 0236, 0237, 0238, 0239, 0250, 0267, 0270, 0276, 0323, 0401–0408, 0428, 0429.
**Decided by** ADR 0162, 0218, 0236, 0237, 0238, 0239, 0250, 0267, 0270, 0276, 0323, 0401–0408, 0428, 0429, 0444–0447.
**Uses:** module, node, declaration and send (Placement), health (Health and repair), person.
- **merge check** — the two statuses a pull request carries before it may merge: the **merge gate**
(`mesh/merge-gate`, the build seat's composed check of the modules the change touches) and the
**repository check** (`mesh/repo-check`, the repository's own `merge-check.sh`)
(ADR 0238). Both judge the merge of the pull request's head into a named **trunk commit**, made in the
build seat's own clone and never pushed (ADR 0323).
- **merge check** — what a pull request carries before it may merge, judging the merge of its head into a
named **trunk commit**, made in the builder's own clone and never pushed (ADR 0323). Until release 4 of
ADR 0429 is delivered, two statuses: the **merge gate** (`mesh/merge-gate`, the build seat's composed check of
the modules the change touches) and the **repository check** (`mesh/repo-check`, the repository's own
`merge-check.sh`) (ADR 0238). From that release, one status, `mesh/check`, written by the checker: the
change's tests, run by the language's build module, and the **composition check**; for a delivery group, one
verdict on every member's head (ADR 0445, ADR 0447).
- **composition check** — whether the machines a change touches still compose with it, run by the assigner
from the modules the indexer and the builder hold, with the composition the controller sends with
(ADR 0446). It replaces the merge gate from release 4 of ADR 0429; the old word is struck once that release
is delivered and every design that still says it is reworded (issue 1303).
- **kept verdict** — a package's passing verdict at one test level, kept by the checker under the digest of
everything its tests read, written once and read-only; a check takes it instead of running an unchanged
package (ADR 0444).
- **trunk commit** — the commit of the trunk a merge check's verdict was judged against: the trunk's head when
the build seat cloned it. The verdict holds for that commit only, and goes out of date when the trunk moves
(ADR 0323).
@@ -852,7 +861,7 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical.
| | taking a consumer off a licence | **unbind** (verb `release`, to rename) | Identity and access |
| | a copy of a work an engine can fetch | **media release** | Media |
| gate | the judgement on a delivery's first node | **first-node gate** | Delivery |
| | the pull request status | **merge gate** | Delivery |
| | the pull request status, until release 4 of ADR 0429 | **merge gate**; from release 4, **composition check** | Delivery |
| | the part that merges a group and moves the source revision | **gate part** (`mesh-delivery-gate`) | Delivery |
| | a failed step stopping its module's later steps (ADR 0136) | *a failed step holds its module* | Placement |
| tier | a level of the mesh | **layer** | Core |
@@ -875,7 +884,8 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical.
| | the operator's terminal command, `mesh-cli` | **the `nox` command** | Operator and conversation |
| knowledge base | the module holding the decision records and research efforts whole | **knowledge base** | The record |
| | the predecessor's operational memory, in older playbooks (issue 430) | none: it no longer exists | — |
| check | a pull request's two statuses | **merge check**, **merge gate**, **repository check** | Delivery |
| check | a pull request's two statuses, one from release 4 of ADR 0429 | **merge check**, **merge gate**, **repository check**; from release 4, `mesh/check` | Delivery |
| | whether the machines a change touches still compose, the assigner's | **composition check** | Delivery |
| | a delivery group's verdict | **composed check** | Delivery |
| | the controller's own examination | **self-check** | Health and repair |
| | a file in `00-META/checks/` | **hq check** | The record |
@@ -4,6 +4,10 @@ status: in-progress
code: [mesh-controller, mesh-catalog modules/mesh-delivery, mesh-delivery, mesh-host, mesh-sdk]
updated: 2026-10-19
decisions:
- "ADR 0447"
- "ADR 0446"
- "ADR 0445"
- "ADR 0444"
- "ADR 0437"
- "ADR 0435"
- "ADR 0434"
@@ -83,13 +87,18 @@ source revision is derived from the keys: every **want** equals its module's **f
group and the modules of the trunk.
- **The builder** claims a build by creating its key, once per fingerprint, and builds it; build-agent becomes
this part.
- **The checker** runs the merge check on built artifacts.
- **The checker** runs the merge check on built artifacts: a change's tests, through the build module of each
module's language and by that language's convention, running only the packages whose inputs changed and
taking the kept verdict of the rest; it writes the change's one status (ADR 0444, ADR 0445, ADR 0447).
- **The gate** merges a group's pull requests once check, review and the operator's Approve agree on the same
heads, and then moves the mesh's source revision in one write.
- **The teller** carries conditions and asks to the operator's phone and is the only writer of an ask's answer.
- **The assigner** writes which fingerprint each node should run, by six rules: the build is done, the
fingerprint is not held, the node is the module's **canary** or the canary runs it healthy, at most `step`
other nodes are ahead when `step` is above zero, every provider runs healthy, and the module's credential for that fingerprint exists.
It also runs the **composition check**: whether the machines a change touches still compose with it, read
from the keys the indexer and the builder hold, with the composition it sends with (ADR 0446). Its module
is made in release 4 for that check alone; its wants come in release 5.
- **The node agent**, the node-engine's own process, applies its wants one module at a time, backs up a data
module first, and writes its haves.
- **The watchman** turns the bus's connections into presence and mirrors every key whose next move a machine
@@ -310,6 +319,53 @@ commit on the SDK's trunk or the head of an SDK pull request the forge holds, op
warrant for those heads in place of an approving forge review (ADR 0421 §9). A member the forge refuses is
merged again on its fresh check while the group's batch stays open for it.
### The check from release 4
*ADR 0444, ADR 0445, ADR 0446, ADR 0447; research 058.*
Until release 4 is delivered, the subsections above are the rule, with their two statuses. From its delivery, a
check is this:
- **One status per change.** A pull request carries one required status, `mesh/check`, written by the checker
on its head; it passes only when the head merged onto its trunk's head passed its tests and the composition
check. For a member of a delivery group it is the group's one verdict, the same on every member's head: every
member's tests, read beside the others' heads, and one composition of all members' changes. It replaces
`mesh/merge-gate` and `mesh/repo-check`; the forge requires it, the checker writes it and the gate reads it from
the same delivery (ADR 0447). `mesh/delivery-group` stays the delivery's view, not a required check. Wherever
the sections above say both checks passed, they read this one status.
- **What the status says.** Its line says the verdict, the tests run and kept at each level, the machines
composed, and how long each part took: waiting in the queue, cloning, the unit level, the integration level's
setup and its running, and the composition. A failure names the test or the machine first. The line links to
the check's full report, which carries the delivery plan's line too (ADR 0447 §3).
- **Tests by the language's convention.** The checker runs a change's tests through the build module of each
module's language (milestone 6's build modules, ADR 0405), with no manifest field and no script per
repository: in Go, `go test` is the unit level and the `integration` build tag the other, so the two levels
are apart by construction; in Node and TypeScript, the type-check and the package's `test` script, and its
`test:integration` script when it has one. A repository with no tests has none, and says so. Each level is
judged by its own bounds: the unit level by its running time (five seconds), the integration level by its
setup (thirty seconds) and its tests' running time (sixty seconds), measured and judged apart. A
repository's `merge-check.sh` goes; hq, which builds no module, keeps its script until issue 1296 settles how
it is checked (ADR 0445).
- **Only what changed runs.** The build module names, from the toolchain, everything each package's tests read,
and the checker keeps a package's passing verdict at each level under the digest of those inputs. A check
runs a package only when no passing verdict is kept under its digest; a check asked again after a failure
runs what failed and what changed, never the whole suite; the change's own new and changed tests run first,
and the check stops at their first failure, before the rest and before the composition. A kept verdict is
written once, by the checker's credential alone, from the result it read, and is addressed by its digest;
each check builds with a cache of its own, so one pull request cannot poison another's verdict (ADR 0444,
issue 482). With every check asked again on a trunk move (ADR 0395), such a re-ask runs only what the move
changed.
- **The composition check is the assigner's.** Whether the machines still compose with a change is checked by
the part that owns what each machine should run. The assigner reads the modules, fingerprints and manifests
the indexer holds and the builds the builder holds, clones no repository but at most the change's own, and
composes only the machines that run or could run a module the change moves or adds, or whose grants or
providers it alters; for a group, once over every member's change, read from the indexer's candidates of the
group, and while the indexer holds none the group's check waits and says why. It composes with the function the
controller sends with, moved into mesh-sdk, so the two agree for one mesh-sdk version. No judge is built from
a change: a change to the composition is proved by its own tests, and a field only a newer composition reads
goes out as optional first. What it fails on, and its warning past twelve rebuilt modules, are today's merge
gate's (ADR 0446, ADR 0237 §2).
## The Approve and the merge
*ADR 0421, ADR 0398 §3, ADR 0406 §1.*
@@ -447,8 +503,9 @@ delivery time.
image and its module retire.
- **Every builder runs the same toolchain, and says so.** Each builder names its toolchain versions with every
build outcome, and the controller's self-check raises a condition while two builders differ.
- **Builds and tests run directly**, as the build seat's own account on its node, in no container. A
repository's `# mesh-check-toolchain` line selects which installed toolchain runs its check.
- **Builds and tests run directly**, as the build seat's own account on its node, in no container. The
build module of each module's language runs its tests by that language's convention; no repository's
script or toolchain line decides it, hq's alone excepted until issue 1296 (ADR 0445).
- **A judge has an account of its own.** A judge built from a sibling's merge (ADR 0382 §3) is built and run as a
second account of the Go build module, whose home, configuration and cache the build seat's account cannot write,
so a check's script cannot change it.
@@ -587,6 +644,21 @@ From ADR 0429 (research 063's done-when, and the live proof each of its releases
20. Each release's pull request reports the controller's code lines against research 063's baseline (111,386
lines on 2026-10-18).
From ADR 0444 to ADR 0447 (research 058's conclusion: a small fix delivered within four minutes after
development, the check's share about a minute):
21. A leaf fix's check takes about a minute, measured as research 058 measured it: the check's log from its
first line to its verdict, plus the time from the change's announcement to its verdict in the delivery,
each part's time as the status's line says it.
22. A change that adds a failing test is answered failed with only that test's package run; a check asked again
after one failed package runs that package alone; a check whose inputs equal an earlier one's runs nothing
and takes every kept verdict.
23. A library or catalogue change's composition check composes only the machines it touches, and clones no
repository but at most the change's own.
24. A pull request carries one required status, and a delivery group one verdict on every member's head, its
line naming what was proved and each part's time; no repository a module is built from holds a
`merge-check.sh`.
## What retires
- The "release branches" and the controller's judge of them (ADR 0358, superseded by ADR 0401).
@@ -635,7 +707,7 @@ release reports the controller's code lines against research 063's baseline (acc
| 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 merge gate'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 | 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 and ends (ADR 0437) | 15 | mesh-delivery (gate, forge bridge, teller), mesh-catalog (mesh-delivery removed, mesh-issues) | opened when it is prepared |
| R4 | The controller asks no build: a build is keyed by its fingerprint, so a merge builds nothing its check built; with milestone 6, toolchains are installed, builders fetch over SSH, and an SDK change ships with its users | 16, 2, 4 | mesh-delivery (builder, checker), mesh-controller (build dispatch deleted; build-agent leaves), mesh-catalog (build modules, ssh-client, gitea), mesh-sdk | 979, 971; the rest opened when it is prepared |
| R4 | The controller asks no build: a build is keyed by its fingerprint, so a merge builds nothing its check built; with milestone 6, toolchains are installed, builders fetch over SSH, and an SDK change ships with its users; a check runs only what changed, its tests by the language's build module, its composition by the assigner, and says in one status what it proved and how long each part took (ADR 0444 to ADR 0447) | 16, 2, 4, 21 to 24 | mesh-delivery (builder, checker, assigner's composition check), mesh-controller (build dispatch and merge gate deleted; build-agent leaves), mesh-catalog (build modules, ssh-client, gitea), mesh-sdk (the composition), the node-engine (`mesh-host`) and mesh-tools (scripts deleted), hq | 979, 971; the check: 1287, 1288, 1289 (kept verdicts, the change's own tests first), 1290, 1291, 1292 (the build modules run the tests), 1293, 1294, 1295 (`merge-check.sh` goes), 1296 (how hq is checked: the operator's), 1297, 1298 (the assigner's composition check), 1299 (the controller's merge gate deleted), 1300, 1301, 1302 (one status), 1303 (the word merge gate struck); the rest opened when it is prepared |
| R5 | The assigner writes what each node should run by its six rules, compared with what the controller sends, and the view shows every difference; the operator answers the asks that need no proof of who answered in the view (ADR 0437 §10) | 17 | mesh-delivery (assigner), mesh-controller (grants keys) | opened when it is prepared |
| 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 |