Merge pull request 'Design 47 and the as-is delivery after release 6: acceptance tests on wants, as-is 04 and 13 as the mesh runs now (issue 1130)' (#477) from fix/1130-after-r6 into main
This commit was merged in pull request #477.
This commit is contained in:
@@ -1,12 +1,11 @@
|
|||||||
---
|
---
|
||||||
layer: as-is
|
layer: as-is
|
||||||
status: implemented
|
status: implemented
|
||||||
code: [mesh-controller, mesh-delivery, mesh-catalog modules/gitea, mesh-catalog modules/mesh-build-go]
|
code: [mesh-delivery, mesh-catalog modules/mesh-delivery-gate, mesh-catalog modules/gitea, mesh-catalog modules/mesh-build-go, mesh-catalog modules/messenger, mesh-catalog modules/mesh-issues, mesh-controller, mesh-host, mesh-sdk]
|
||||||
updated: 2026-10-24
|
updated: 2026-10-26
|
||||||
decisions:
|
decisions:
|
||||||
- "ADR 0239"
|
- "ADR 0239"
|
||||||
- "ADR 0267"
|
- "ADR 0267"
|
||||||
- "ADR 0276"
|
|
||||||
- "ADR 0282"
|
- "ADR 0282"
|
||||||
- "ADR 0289"
|
- "ADR 0289"
|
||||||
- "ADR 0304"
|
- "ADR 0304"
|
||||||
@@ -17,71 +16,120 @@ decisions:
|
|||||||
- "ADR 0382"
|
- "ADR 0382"
|
||||||
- "ADR 0395"
|
- "ADR 0395"
|
||||||
- "ADR 0398"
|
- "ADR 0398"
|
||||||
|
- "ADR 0429"
|
||||||
- "ADR 0524"
|
- "ADR 0524"
|
||||||
- "ADR 0525"
|
- "ADR 0525"
|
||||||
- "ADR 0527"
|
- "ADR 0527"
|
||||||
- "ADR 0528"
|
- "ADR 0528"
|
||||||
- "ADR 0529"
|
- "ADR 0529"
|
||||||
|
- "ADR 0539"
|
||||||
|
- "ADR 0546"
|
||||||
|
- "ADR 0547"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Delivery — from a merge to the nodes, as it runs
|
# Delivery — from a merge to the nodes, as it runs
|
||||||
|
|
||||||
What runs on 2026-10-24, after the delivery of release 4 and release 5's first half (milestone R4g, design 47),
|
What runs on 2026-10-26, after the delivery of release 6 (milestone R6 of
|
||||||
read from the live controller (`mesh-controller.modules`, `.seats`, `.plans`), the delivery checker's `checker_status`
|
[to-be 47](../01-to-be/47-delivery-from-commit-to-delivered.md), ADR 0539), read from the code on each repository's
|
||||||
and the machines' module lists. It is what [to-be 47](../01-to-be/47-delivery-from-commit-to-delivered.md) has not yet
|
main (`mesh-delivery`, the gate in `mesh-catalog`, the node agent in `mesh-host`, `mesh-controller`) and from the live
|
||||||
finished: the node agent applying wants and the deletion of plans are release 6, and the controller still plans,
|
mesh: the controller's seat verbs, `mesh-controller.modules`, the gate's `table`, and the view's `assigner_wants` and
|
||||||
orders and sends a delivery's builds to the machines. Until 2026-10-23 this document described the pipeline with the
|
`node_haves`. Until 2026-10-26 this document described release 5, in which the controller still made a delivery plan
|
||||||
build agent, the build queue and the two statuses `mesh/merge-gate` and `mesh/repo-check`, which no longer run.
|
for each merge, ordered it in tiers and sent whole declarations to the machines; none of that runs any more.
|
||||||
|
|
||||||
## Who does what
|
## Who does what
|
||||||
|
|
||||||
- **The parts of `mesh-delivery`** are modules of one repository, each a process with its own bus credential that
|
- **The parts of `mesh-delivery`** are modules of one repository, each a process with its own bus credential that
|
||||||
watches keys and writes keys (design 47, ADR 0429). Running now: the forge bridge (`mesh-delivery-forge-bridge`),
|
watches keys and writes keys (ADR 0429). Running now: the forge bridge, the indexer, the checker, the teller and the
|
||||||
the indexer, the checker, the gate (`mesh-delivery-gate`, which holds the seat `mesh-delivery`), the teller and
|
watchman on the control-node; the builder and the status view (`mesh-delivery-view`) on the workstation; and the
|
||||||
the watchman on the control-node; the builder (`mesh-delivery-builder`) and the status view on the workstation;
|
assigner on the home server. The gate (`mesh-delivery-gate`, holding the seat `mesh-delivery`) is a module of
|
||||||
and the assigner (`mesh-delivery-assigner`) on the home server (ADR 0524, ADR 0528).
|
`mesh-catalog` and runs on the control-node.
|
||||||
- **The forge bridge** turns the forge's events into stream messages and is the only part that calls the forge. The
|
- **The forge bridge** turns the forge's events into stream messages and is the only part that calls the forge; the
|
||||||
forge module (`gitea`, on the control-node) still announces them through the forge's system webhook.
|
forge module (`gitea`) still announces them through the forge's system webhook.
|
||||||
- **The indexer** computes each module's fingerprint at the merge preview; **the builder** claims a build once per
|
- **The indexer** writes each module's fingerprint at the merge preview and at a trunk merge; **the builder** claims a
|
||||||
fingerprint and orders it as an ask on the stream of the artifact's language.
|
build once per fingerprint and orders it as an ask on the stream of the artifact's language.
|
||||||
- **The build modules** (`mesh-build-go` and `mesh-build-node` on three machines, `mesh-build-image` on one; ADR 0525) hold the
|
- **The build modules** (`mesh-build-go` on all four machines, `mesh-build-node` on three, `mesh-build-image` on one;
|
||||||
node seats `node-build-go`, `node-build-node` and `node-build-image`. Each pulls asks from the bus's work-queue
|
ADR 0525) hold the node seats `node-build-go`, `node-build-node` and `node-build-image` and pull asks from the bus's
|
||||||
streams (deliveries first, then checks, then re-checks) while its node has a free slot of build capacity; no part
|
work-queue streams (deliveries first, then checks, then re-checks) while their node has a free slot of build
|
||||||
chooses the node. The seat `node-build-agent` and the module `build-agent` have no holder any more, and the seat
|
capacity.
|
||||||
`mesh-build-machine` has none either.
|
- **The checker** runs the merge check and writes the one status `mesh/check`, and serves a **try** on a pushed
|
||||||
- **The checker** (`mesh-delivery-checker`) runs the merge check: a change's tests through the build module of each
|
branch. The forge requires no status on any repository (ADR 0534), and no repository holds a `merge-check.sh`
|
||||||
language, running only packages whose inputs changed, and writes the one status `mesh/check`. It also serves a
|
(ADR 0529).
|
||||||
**try** (`checker_try`, `checker_try_read`): the same check on a pushed branch, before a pull request. `checker_status`
|
- **The gate** keeps one key per pull request and the merge's states only: `proposed`, `ready`, `rejected`, `held`,
|
||||||
shows the steps in flight by node and the candidates still without a verdict.
|
`merged` and `closed`, read from its `table` verb. On the operator's Approve it merges a delivery group's pull
|
||||||
- **The gate** merges a delivery group's pull requests once the check, the review and the operator's Approve agree on
|
requests in one pass and writes their merged heads as one revision of `source.main`. It sends nothing to a
|
||||||
the same heads. The forge requires no status on any repository (ADR 0534). The scripts `merge-check.sh` are gone from every repository (ADR 0529).
|
machine and asks the controller nothing.
|
||||||
- **The assigner** composes the machines a change touches (the composition check the checker reads) and writes which
|
- **The controller** (`mesh-controller`, on the control-node) keeps registration, placement in its assignments
|
||||||
fingerprint each node should want, by its six rules; it only compares wants with what the controller sends.
|
bucket and every node's inputs, and composes: on events it writes each module's signed composition for each node at
|
||||||
- **The controller** (`mesh-controller`, on the control-node) plans, orders, sends and judges. It computes a delivery plan for the
|
each fingerprint into the node's bucket `composed-<node>`, with its digest and its judgement of the move in
|
||||||
files a merge changes, moves only modules whose build source changed with their build dependents, and writes the
|
`mesh-controller_composed`, and it issues a module's credential and grant when its build is done. It plans,
|
||||||
chain's links it owns. On 2026-10-24 the seat still lists 64 verbs, `queue` and `replay` among them; whether
|
orders and sends nothing: of its seat's 65 verbs, 20 are refused by name with their replacement, among them
|
||||||
those still do work was not read here, and the build agent they served has no holder.
|
`plans`, `plan`, `push`, `deliver`, `delivery-stop`, `delivery-order` and `delivery-walks` (read 2026-10-26 01:20).
|
||||||
|
- **The assigner** writes each node's want of each module, `want.<node>.<module>`, naming a fingerprint and the
|
||||||
|
digest of the one composition it allows, when its seven rules hold: 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` others ahead, every provider
|
||||||
|
runs healthy, the grant exists and the composition exists. In the code the canary is the first of the module's
|
||||||
|
nodes by name that is online (one ring), and rule 4 always holds, because the mesh keeps no `step`. It also runs
|
||||||
|
the composition check the checker reads. Its differences bucket, from release 5's comparison with what the
|
||||||
|
controller sent, is no longer written.
|
||||||
|
- **Two ways around the rules, both by hand.** A **put** (ADR 0546), written by the assigner's tool `assigner_put`,
|
||||||
|
puts one version of a module on one node: while a put owns a node's want of a module, from its ask until it ends,
|
||||||
|
the rules pass over that want. And the operator's credential may write a want itself, with a composition the
|
||||||
|
operator signed and wrote through mesh-sdk's `mesh-hand-compose` (ADR 0539 §10).
|
||||||
|
- **The node agent**, a process of the node-engine (`mesh-host`) on every node, watches its node's wants and its
|
||||||
|
bucket of compositions, and applies a module only when the want's fingerprint or digest differs from what runs,
|
||||||
|
and only the composition whose digest the want names, after checking its signature. It asks its node's
|
||||||
|
`node-backup` seat to back up a data module first and waits for the backup's end. It writes the have,
|
||||||
|
`have.<node>.<module>` in `node-engine_have`, with the fingerprint, the composition's digest, the phase and the
|
||||||
|
health. A failed apply is retried by the next change of the want or the composition; an apply that failed only
|
||||||
|
because the bus did not answer for a moment is retried with a bounded backoff, and at once when the bus is back.
|
||||||
|
- **The watchman** mirrors every want as a pulse owed by that node's agent until its have names the want's
|
||||||
|
fingerprint, so a node that does not move shows as a stall.
|
||||||
|
- **The status view** derives from `source.main`, the wants and the haves whether the source revision is
|
||||||
|
delivered, and says the event `delivered` once per revision, and `moving`, `settled` and `stuck` once for a
|
||||||
|
module on a node at one composition. The messenger holds the operator's notices on those events, and the issue
|
||||||
|
tracker hears `delivered`.
|
||||||
|
- **The grants part** (`mesh-grants`, on the control-node; ADR 0547) publishes each assignment's membership on the
|
||||||
|
assignments stream when it differs from the one last published. The bus's user list, assertions and grants it
|
||||||
|
composes only in its own state, compared with what the bus holds, and they take no effect; the controller still
|
||||||
|
composes the user list the bus loads.
|
||||||
|
|
||||||
## From a merge to a delivery plan
|
## From a merge to the nodes
|
||||||
|
|
||||||
- A pull request's head is built and checked as it comes in. One status, `mesh/check`, carries the verdict; a delivery
|
- A pull request's head is built and checked as it comes in; one status, `mesh/check`, carries the verdict, and a
|
||||||
group has one verdict for every member. A move of the trunk asks the checks again, and a running check stops itself
|
delivery group has one verdict for every member. A move of the trunk asks the checks again, and a running check
|
||||||
when its head or trunk commit moves.
|
stops itself when its head or trunk commit moves.
|
||||||
- A merge is made by the gate on the operator's Approve; the controller then makes a delivery plan, tiered along the
|
- The gate merges on the operator's Approve and moves the source revision in one write. Nothing collects merges or
|
||||||
module graph, and sends it. `mesh-controller.plans` lists the plans and the delivery plans' tiers; a plan that
|
waits for others: the indexer writes the new fingerprints, the builder claims each new one once, the controller
|
||||||
fails on a node says so and is retried by hand.
|
composes and grants on the done build, and the assigner writes each want once its rules hold, the canary first.
|
||||||
|
- Each node applies its own wants one module at a time and writes its haves; the source revision is delivered when
|
||||||
|
every want equals its module's fingerprint and every have equals its want, running and healthy. Read on
|
||||||
|
2026-10-26 at 01:20: 303 wants, every one equal to its node's have in fingerprint and composition digest, and 12
|
||||||
|
fingerprints held.
|
||||||
- **hq** builds no module: the checker runs hq's Go tests (`go test ./...`) as its check (ADR 0527).
|
- **hq** builds no module: the checker runs hq's Go tests (`go test ./...`) as its check (ADR 0527).
|
||||||
|
|
||||||
## Where the record of what runs lives
|
## Where the record of what runs lives
|
||||||
|
|
||||||
Fingerprints, builds, verdicts and wants are keys in the bus's key-value buckets of the parts; builds' files are in
|
Fingerprints, builds, verdicts, wants and haves are keys in the parts' buckets on the bus; compositions are in each
|
||||||
the artifact store by digest; packages are versions in the package registry. Plans, rollouts with their tiers,
|
node's `composed-<node>` bucket, readable only by that node, with a file over 64 KiB in the object store; builds'
|
||||||
assignments and settings are still rows in the controller's store. An assignment names its module and node but not
|
files are in the artifact store by digest; packages are versions in the package registry. The controller
|
||||||
the build, artifact or plan that put it there.
|
still records every build it takes in, in its builds bucket (`RecordBuild` in `cmd/mesh-controller/key_takein.go`); its
|
||||||
|
assignments bucket keeps placement alone, and its rollouts bucket keeps the record of releases 1 to 5 read-only, and
|
||||||
|
nothing writes it now.
|
||||||
|
|
||||||
## What is not covered
|
## What is not covered
|
||||||
|
|
||||||
The node agent does not yet apply wants: a node runs what the controller sent. The checker's left-running keys of
|
Nothing checks the delivery budget: the over-budget condition and the gate's `times` went with release 6, and no
|
||||||
build modules that stopped (`checker_status`'s `left_running`) are listed and hold no place. The integration tests run
|
reader of the view's `settled` and `delivered` events measures it yet (issue 1945, note 10). The bus's own move stays
|
||||||
in each repository's check; there are no end-to-end tests of delivery yet, and the lab is not used (the operator,
|
a person's step through the controller's `bus` verb (ADR 0539 §15). The checker's left-running keys of build modules
|
||||||
2026-10-16).
|
that stopped (`checker_status`'s `left_running`) are listed and hold no place. There are no end-to-end tests of
|
||||||
|
delivery, and the lab is not used (the operator, 2026-10-16).
|
||||||
|
|
||||||
|
## How it is checked
|
||||||
|
|
||||||
|
- `mesh-delivery-view.assigner_wants` and `mesh-delivery-view.node_haves`: each want beside its have; `indexer_modules`
|
||||||
|
and `builder_builds` for the fingerprints and builds they name.
|
||||||
|
- `mesh-delivery.table`: the gate's states and transitions; `mesh-delivery.deliveries` and `show` for one delivery.
|
||||||
|
- `mesh-controller.seats` and `mesh_overview`: the controller's verbs, and which are refused by name.
|
||||||
|
- The code: `mesh-delivery` (`modules/mesh-delivery-assigner/internal/assign`, `modules/mesh-delivery-view/internal/view`,
|
||||||
|
`modules/mesh-delivery-watchman/internal/watch`, `modules/mesh-grants`), `mesh-host` (`internal/agent`,
|
||||||
|
`cmd/mesh-host/nodeagent.go`), and the gate in `mesh-catalog` (`modules/mesh-delivery-gate`).
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
layer: as-is
|
layer: as-is
|
||||||
status: implemented
|
status: implemented
|
||||||
code: [mesh-tools, mesh-host, mesh-controller]
|
code: [mesh-tools, mesh-host, mesh-controller]
|
||||||
updated: 2026-10-24
|
updated: 2026-10-26
|
||||||
decisions:
|
decisions:
|
||||||
|
- "ADR 0539"
|
||||||
|
- "ADR 0360"
|
||||||
- "ADR 0524"
|
- "ADR 0524"
|
||||||
- "ADR 0525"
|
- "ADR 0525"
|
||||||
- "ADR 0152"
|
- "ADR 0152"
|
||||||
@@ -21,17 +23,20 @@ decisions:
|
|||||||
through `mesh_overview`, `mesh_machine`, `mesh_runtimes` and `mesh_describe`. Checked: the
|
through `mesh_overview`, `mesh_machine`, `mesh_runtimes` and `mesh_describe`. Checked: the
|
||||||
catalogue (`mesh-catalog`) carries no module named `mesh-console` any more — the name survives only
|
catalogue (`mesh-catalog`) carries no module named `mesh-console` any more — the name survives only
|
||||||
in the glossary's retired-words list and in a test fixture — and none of the four nodes answers a
|
in the glossary's retired-words list and in a test fixture — and none of the four nodes answers a
|
||||||
module of that name.
|
module of that name. How the tool runner reaches a node, its count of modules and tools and the
|
||||||
|
controller's verbs were read again on 2026-10-26, after the delivery of release 6 (ADR 0539).
|
||||||
|
|
||||||
## What it is now
|
## What it is now
|
||||||
|
|
||||||
**The tool runner is one of the mesh's core components**, named `node-tools` beside
|
**The tool runner is one of the mesh's core components**, named `node-tools` beside
|
||||||
`mesh-controller`, `mesh-host` (the node-engine) and `nats` (the bus) — the mesh's own repositories'
|
`mesh-controller`, `mesh-host` (the node-engine) and `nats` (the bus) — the mesh's own repositories'
|
||||||
check treats the four the same way, as the core whose health the mesh itself defines rather than a
|
check treats the four the same way, as the core whose health the mesh itself defines rather than a
|
||||||
module's own. `mesh-host` and `mesh-controller` supervise, compose and account for it as a core
|
module's own. Since release 6 it reaches each node the way every module does: the controller composes
|
||||||
process rather than as an ordinary assignment (`ComponentNodeTools`/`BusNodeTools` in both, the
|
and signs its composition for that node, the assigner writes the node's want of it, and the
|
||||||
witness and lease code that restarts and rolls it back, the account named `<node>.node-tools` on
|
node-engine's node agent applies it and writes its have. What stays particular to it is the account
|
||||||
the bus).
|
named `<node>.node-tools` on the bus (`BusNodeTools` in `mesh-controller`) and the node-engine's
|
||||||
|
witness and lease code that puts back a tool runner that does not come up (`ComponentNodeTools` in
|
||||||
|
`mesh-host`, ADR 0360 §9).
|
||||||
|
|
||||||
**It still carries a manifest, `node-tools/module.json` in `mesh-tools`,** and that manifest is
|
**It still carries a manifest, `node-tools/module.json` in `mesh-tools`,** and that manifest is
|
||||||
where its grants live: `invokes` names `*`, so its account may call every tool on the mesh;
|
where its grants live: `invokes` names `*`, so its account may call every tool on the mesh;
|
||||||
@@ -60,7 +65,7 @@ body per request, no session and no event stream (`node-tools/internal/console/m
|
|||||||
`mesh_machine`, `mesh_search`, `mesh_describe`, `mesh_call`, `mesh_runtimes` and `mesh_wait`. The
|
`mesh_machine`, `mesh_search`, `mesh_describe`, `mesh_call`, `mesh_runtimes` and `mesh_wait`. The
|
||||||
handshake's `instructions` text names all seven and the four address forms. `mesh_overview` is
|
handshake's `instructions` text names all seven and the four address forms. `mesh_overview` is
|
||||||
where the mesh-wide count of modules and tools is read live — a number copied into this document
|
where the mesh-wide count of modules and tools is read live — a number copied into this document
|
||||||
would drift; asked on 2026-10-17 it answered 103 modules and 645 tools across the whole mesh, with
|
would drift; asked on 2026-10-26 it answered 115 modules and 714 tools across the whole mesh, with
|
||||||
two module instances (`route-proxy` on two of the nodes) named as not answering rather than silently
|
two module instances (`route-proxy` on two of the nodes) named as not answering rather than silently
|
||||||
absent.
|
absent.
|
||||||
|
|
||||||
@@ -94,8 +99,10 @@ command, not inline, because one call blocks until it answers or times out.
|
|||||||
|
|
||||||
**These already answer directly, not as a stated future.** Beside every assigned module's tools,
|
**These already answer directly, not as a stated future.** Beside every assigned module's tools,
|
||||||
the tool runner asks the `mesh-controller` seat for its own verbs the same way (ADR 0154): measured
|
the tool runner asks the `mesh-controller` seat for its own verbs the same way (ADR 0154): measured
|
||||||
live, the mesh-controller runtime is one instance, mesh-wide, and it answers 64 verbs for that one
|
live on 2026-10-26, the mesh-controller runtime is one instance, mesh-wide, and it answers 65 verbs for
|
||||||
seat (`status`, `push`, `assign`, `build`, `artifacts` and the rest), and the `mesh-controller`
|
that one seat (`status`, `assign`, `modules`, `artifacts` and the rest), of which 20 are refused by
|
||||||
|
name with what replaces them: the delivery verbs release 6 removed (`plans`, `plan`, `push`,
|
||||||
|
`deliver` among them) and the build verbs of release 4 (`build`, `queue` among them). The `mesh-controller`
|
||||||
*module* answers none of its own — it serves no module tools, only its seat's, exactly as design 33
|
*module* answers none of its own — it serves no module tools, only its seat's, exactly as design 33
|
||||||
described while it was still only designed. The 56-to-93 seat-verb counts each node's tool runner
|
described while it was still only designed. The 56-to-93 seat-verb counts each node's tool runner
|
||||||
answers (below) are a different thing: the tool runner serves the verbs of whichever node-scoped
|
answers (below) are a different thing: the tool runner serves the verbs of whichever node-scoped
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
layer: to-be
|
layer: to-be
|
||||||
status: in-progress
|
status: in-progress
|
||||||
code: [mesh-controller, mesh-catalog modules/mesh-delivery-gate, mesh-delivery, mesh-host, mesh-sdk, hq 00-META/checks]
|
code: [mesh-controller, mesh-catalog modules/mesh-delivery-gate, mesh-delivery, mesh-host, mesh-sdk, hq 00-META/checks]
|
||||||
updated: 2026-10-24
|
updated: 2026-10-26
|
||||||
decisions:
|
decisions:
|
||||||
- "ADR 0539"
|
- "ADR 0539"
|
||||||
- "ADR 0536"
|
- "ADR 0536"
|
||||||
@@ -172,8 +172,8 @@ It lands in six releases, each leaving the mesh working, each one milestone belo
|
|||||||
with one switch-over and no rehearsal (ADR 0524 §1). Until the
|
with one switch-over and no rehearsal (ADR 0524 §1). Until the
|
||||||
release that replaces it is delivered, each section from here to *The bootstrap* stays this design and its rule
|
release that replaces it is delivered, each section from here to *The bootstrap* stays this design and its rule
|
||||||
(ADR 0429 §21); each is rewritten when the release that replaces it is prepared (issue 1130). Release 6's were
|
(ADR 0429 §21); each is rewritten when the release that replaces it is prepared (issue 1130). Release 6's were
|
||||||
rewritten when it was prepared, from ADR 0539: until its delivery the plans of release 5 run, as the as-is
|
rewritten when it was prepared, from ADR 0539, and its acceptance tests restated after its delivery; release 6
|
||||||
design says, and ADR 0539's clauses hold from that delivery (ADR 0539 §20).
|
is delivered, so ADR 0539's clauses hold (ADR 0539 §20), and the as-is design describes the delivery as it runs.
|
||||||
|
|
||||||
## The parts
|
## The parts
|
||||||
|
|
||||||
@@ -740,23 +740,22 @@ the operator for the bus node's want (ADR 0539 §15).
|
|||||||
- **A build before its want.** The controller takes every module, the builder's own and the build modules among
|
- **A build before its want.** The controller takes every module, the builder's own and the build modules among
|
||||||
them, from the builder's done key whose artifacts all name a reference; a module whose key is not yet done
|
them, from the builder's done key whose artifacts all name a reference; a module whose key is not yet done
|
||||||
waits under the assigner's first rule and fails nothing (ADR 0524 §7, ADR 0539 §18).
|
waits under the assigner's first rule and fails nothing (ADR 0524 §7, ADR 0539 §18).
|
||||||
- **The switch to release 6 is one plan, release 5's last.** Release 5's controller runs the group's plan with
|
- **The switch to release 6 was one plan, release 5's last** (history: it is delivered). Release 5's controller ran
|
||||||
the new node-engine and the new controller in one tier (issue 1942), so every node's last declaration names
|
the group's plan with the new node-engine and the new controller in one tier (issue 1942), so every node's last
|
||||||
the new node-engine and carries the operator's public key, and the control-node's names the new controller
|
declaration named the new node-engine and carried the operator's public key, and the control-node's named the new
|
||||||
too. Each node applies it with the node-engine it runs; the new controller writes every composition at its
|
controller too. Each node applied it with the node-engine it ran; the new controller wrote every composition at
|
||||||
start, and the assigner's wants equal what runs. For that plan one machine at a time yields: each new
|
its start, and the assigner's wants equalled what ran. For that plan one machine at a time yielded: each new
|
||||||
node-engine is judged by its launcher, and the new controller by the node-engine's witness. A node away during
|
node-engine was judged by its launcher, and the new controller by the node-engine's witness. A node away during
|
||||||
the switch finds its last declaration on the bus's stream of declarations when it returns; the controller
|
the switch finds its last declaration on the bus's stream of declarations when it returns; the controller
|
||||||
deletes that stream and the nodes' consumers only once every node's have names the new node-engine. The
|
deletes that stream and the nodes' consumers only once every node's have names the new node-engine. The merge
|
||||||
merge waits until every node is present (ADR 0539 §11). The switch works only because the bus's user list that
|
waited until every node was present (ADR 0539 §11). The switch worked only because the bus's user list that
|
||||||
release 5's controller composes already grants what release 6 uses: the controller writing compositions and
|
release 5's controller composed already granted what release 6 uses: the controller writing compositions and
|
||||||
their digests, each node-engine reading its own compositions and wants, asking its backup holder and hearing the
|
their digests, each node-engine reading its own compositions and wants, asking its backup holder and hearing the
|
||||||
backup's end, the assigner reading the digests, and the operator's account writing the hand path. That grant is
|
backup's end, the assigner reading the digests, and the operator's account writing the hand path; that grant was
|
||||||
delivered first by release 5's controller, like issue 1942, as issue 1945's fix before the switch. The
|
delivered first, as issue 1945's fix before the switch. The node-engine's setting `operator-signers` holds the
|
||||||
node-engine's setting `operator-signers` must hold the operator's public key before the switch, or no operator
|
operator's public key, or no operator key is trusted and the hand path cannot work (ADR 0539 §3). At its first
|
||||||
key is trusted and the hand path cannot work (ADR 0539 §3). At its first start the new controller deletes the
|
start the new controller deleted the buckets of plan state (the merge window's, the silent sends' and the
|
||||||
buckets of plan state (the merge window's, the silent sends' and the building plan's hold) and says each
|
building plan's hold) and said each deletion as its event (ADR 0539 §13).
|
||||||
deletion as its event (ADR 0539 §13).
|
|
||||||
|
|
||||||
### Delivering the controller, the builder or a build module without the builder
|
### Delivering the controller, the builder or a build module without the builder
|
||||||
|
|
||||||
@@ -790,28 +789,60 @@ way is written down before the switch (ADR 0526, which ADR 0522 §6 asked of R4g
|
|||||||
What the build proves before this design is implemented (research 055's direction):
|
What the build proves before this design is implemented (research 055's direction):
|
||||||
|
|
||||||
1. A feature across the controller and the catalogue with a new seat verb is delivered as one group, with no
|
1. A feature across the controller and the catalogue with a new seat verb is delivered as one group, with no
|
||||||
`after:` line, one composed check, one Approve and one delivery plan: its merges are one batch, each module is
|
`after:` line, one composed check and one Approve: its merges move one source revision, each module it changes
|
||||||
built once and sent once, its commits are carried by that one plan, and the plan names the edge that placed
|
is built once, and every want naming one of those fingerprints is written by the assigner's seven rules, with
|
||||||
each tier.
|
no order written by anyone.
|
||||||
2. An SDK change and a Go module using it are delivered as one group.
|
2. An SDK change and a Go module using it are delivered as one group.
|
||||||
3. A data module is backed up before a delivery moves it, and a failed backup holds the delivery.
|
3. A data module is backed up by its node's backup seat before the node agent applies a new fingerprint of it,
|
||||||
|
and a failed backup holds that module on that node, its have in phase `held`, while every other want moves.
|
||||||
4. A build on any builder uses the installed toolchain with no container, and a toolchain update rebuilds only
|
4. A build on any builder uses the installed toolchain with no container, and a toolchain update rebuilds only
|
||||||
modules of that language when its version changes.
|
modules of that language when its version changes.
|
||||||
5. Two merges into one repository within a minute leave each open pull request with one queued check, by the
|
5. Two merges into one repository within a minute leave each open pull request with one queued check, by the
|
||||||
stream's rule.
|
stream's rule.
|
||||||
6. The operator's Approve is asked within seconds of the event of a pull request's checks passing, with no ready
|
6. The operator's Approve is asked within seconds of the event of a pull request's checks passing, with no ready
|
||||||
mark, label or comment written by anyone.
|
mark, label or comment written by anyone.
|
||||||
7. A controller replaced in the middle of a rollout resumes it with no step lost or repeated.
|
7. A controller, an assigner or a node agent replaced while a source revision is being delivered carries on from
|
||||||
8. The merge window closes by its key's expiry.
|
its keys: no composition, want or have is lost, and no module is applied again whose have already equals its
|
||||||
9. A hotfix to a module the running feature's delivery does not touch reaches the machines in minutes, beside it.
|
want.
|
||||||
10. For any module on any node, one read of its assignment names the commit, build, artifact or package and the
|
8. Nothing collects merges: a merge moves the source revision in one write, and the assigner writes the wants it
|
||||||
rollout that put it there, and one read of that rollout lists every assignment it changed.
|
allows with no window, no key's expiry and no timer between them.
|
||||||
11. Two merges into one repository while a delivery of that repository runs are both delivered by the next plan,
|
9. A hotfix to a module that the source revision being delivered does not touch reaches the machines in minutes,
|
||||||
with no person's release and nothing held in mesh-delivery.
|
beside it: its wants move on its own build, canary and providers.
|
||||||
12. No table in the controller's store holds builds, rollouts or assignments.
|
10. For any module on any node, one read of its have names the fingerprint and composition it runs, one read of
|
||||||
|
its want the same or what it should run, and the fingerprint names the source revision, the build and its
|
||||||
|
artifact or package.
|
||||||
|
11. Two merges into one repository while its modules are moving are two source revisions: a node is wanted the
|
||||||
|
newer fingerprint once its rules hold, a fingerprint nobody wants any more is never applied, and nothing is
|
||||||
|
released by a person or held in the gate.
|
||||||
|
12. No table in the controller's store holds builds, deliveries or assignments: builds are the builder's keys,
|
||||||
|
wants the assigner's, haves the node agents', and placement the controller's assignments bucket.
|
||||||
|
|
||||||
Tests 1, 3, 7, 8, 9, 10 and 11 were proved by the milestones that built them, on the plans and rollouts of their
|
Tests 1 to 12 are stated as they hold from release 6. Tests 1, 3, 7, 8, 9, 10 and 11 were first proved by
|
||||||
time; from release 6, tests 18 and 19 prove what of them still holds without a plan.
|
milestones 1 to 5 in the shape of their time, the controller's plans and what it sent (the milestones table keeps
|
||||||
|
it). Restated, each has its own proof, or says it has none yet:
|
||||||
|
|
||||||
|
- **Tests 1 and 8, and the assigner's half of test 7:** test 18 (scenario A, three repositories through the keys
|
||||||
|
alone; scenario D, the assigner replaced, in the assigner's integration test
|
||||||
|
`TestTheAssignerReplacedResumesWithNothingLostOrRepeated`). **Tests 8 and 12:** test 19 (the window, the batches,
|
||||||
|
the plans and their verbs deleted from the code).
|
||||||
|
- **Test 3:** the node-engine's integration test `TestNatsADataModuleAsksItsBackupFirstAndIsHeldWhenItFails`
|
||||||
|
(`cmd/mesh-host/nodeagent_integration_test.go`, R6-A AC5) proves the backup first and the hold with phase `held`.
|
||||||
|
That every other want moves meanwhile is not yet proved by a test; it shows on the live mesh at the first failed
|
||||||
|
backup, in the view's wants beside the haves.
|
||||||
|
- **Test 7, the node agent's and the controller's halves:** a node agent restarted on its own haves applies nothing
|
||||||
|
(`internal/agent/agent_test.go`, `TestStartingOnItsOwnHaveAppliesNothing`, at the unit level), and a controller
|
||||||
|
writes a composition once and again only when it changes (`composed_writer_test.go`,
|
||||||
|
`TestACompositionIsWrittenOnceAndAgainOnlyWhenItChanges`). A controller replaced while a source revision is being
|
||||||
|
delivered is not yet proved; it shows at the next delivery of the controller, in the view.
|
||||||
|
- **Test 9:** not yet proved under release 6. Each rule holding a want back on its own is a unit test of the assigner
|
||||||
|
(`internal/assign/wants_test.go`, `TestEachRuleHoldsTheWantBack`); the hotfix beside a moving source revision shows
|
||||||
|
live at the first such pair, read in the view's wants and haves.
|
||||||
|
- **Test 10:** a live read on 2026-10-26 at 01:20: one node's have of `avahi` named its fingerprint and composition digest,
|
||||||
|
its want named the same, and the builder's build of that fingerprint (`builder_build`) named its artifact by digest.
|
||||||
|
In all, 303 wants equalled their haves in fingerprint and digest.
|
||||||
|
- **Test 11:** half proved. The node agent applies only the composition its current want names
|
||||||
|
(`internal/agent/agent_test.go`, `TestTheRevisionAWantNamesIsAppliedFromHistory`); two merges of one repository
|
||||||
|
while its modules move are not yet proved live, and show at the first such pair in the view.
|
||||||
|
|
||||||
From ADR 0429 (research 063's done-when, and the live proof each of its releases names):
|
From ADR 0429 (research 063's done-when, and the live proof each of its releases names):
|
||||||
|
|
||||||
@@ -821,8 +852,9 @@ From ADR 0429 (research 063's done-when, and the live proof each of its releases
|
|||||||
15. A group of two repositories merges as one source revision, and every module's fingerprint the indexer
|
15. A group of two repositories merges as one source revision, and every module's fingerprint the indexer
|
||||||
writes equals the controller's source fingerprint.
|
writes equals the controller's source fingerprint.
|
||||||
16. A merge builds nothing its check built, and a hotfix's build waits for no other build.
|
16. A merge builds nothing its check built, and a hotfix's build waits for no other build.
|
||||||
17. A day of deliveries shows no difference between the assigner's wants and what the controller sent that the
|
17. A day of deliveries in release 5 showed no difference between the assigner's wants and what the controller
|
||||||
six rules do not explain.
|
sent that the six rules then in force did not explain. That was proved in R4g; the differences bucket is kept
|
||||||
|
read-only as its evidence (ADR 0539 §8).
|
||||||
18. On the live mesh a milestone of three repositories reaches every node through the keys alone (research 063's
|
18. On the live mesh a milestone of three repositories reaches every node through the keys alone (research 063's
|
||||||
scenario A), and the assigner replaced in the middle of it resumes with nothing lost or repeated (scenario
|
scenario A), and the assigner replaced in the middle of it resumes with nothing lost or repeated (scenario
|
||||||
D, once).
|
D, once).
|
||||||
|
|||||||
Reference in New Issue
Block a user