To-be 48 Phases B to E are built: what each chose, and what is still to read on the live mesh
mesh/merge-gate pass: the change touches no module of the mesh's graph
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery delivered

This commit is contained in:
jochen
2026-10-07 16:17:57 +02:00
parent 8ff22e4d9b
commit e453da3a3b
@@ -1,7 +1,7 @@
---
layer: to-be
status: in-progress
code: [mesh-host, mesh-controller, mesh-lab]
code: [mesh-host, mesh-controller, mesh-lab, mesh-catalog]
updated: 2026-10-07
decisions:
- 02-DECISIONS/0240-a-module-says-how-it-is-healthy-and-the-node-engine-judges-it.md
@@ -269,6 +269,75 @@ Still to do for Phase A's "done when": every machine's report carrying a state f
resource, and a module stopped on purpose raised and cleared, are read on the live mesh once both are rolled
out — the node-engine first, then the controller.
## As built — Phases B to E
Each phase is its own set of pull requests, none merged yet. What the build chose where this design left it
open:
**Phase B — the field.**
- **Its words.** On a long-running resource, `health` carries `kind`, the endpoint by its `listens` name, for
http a `path`, the `status` expected (none: any answer under 400), a text the answer must hold and the
scheme, for exec a `command` run by the container's shell, for tool a `tool`, the timing as durations
(`interval`, `timeout`, `grace`) and `looks`, and `needs`. A `port`, `address`, `host`, `url` or `ip` is
refused by name, as is every other key; so is `health` on a step, on anything scheduled and on a service
not stated running.
- **Sent only to an engine that reads it.** The engine's statement now says contract 2; the controller
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 merge gate 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
makes; an exec or adopted check from the inspect liveness already makes, read out of the container's whole
state — naming the check's own key fails the runtime's whole read for a container that carries none. The
runtime's retries are the declared looks and its start period the grace; only these two kinds are part of
what a container is, so declaring an http or tcp check recreates nothing, and adopting an image's check
recreates the container once. A tool is asked on the module's tool at its own machine's instance, the one
subject the engine is granted for it; it answers healthy or not, with why.
- **The state.** Starting until the check passed (a pass inside the grace counts); healthy once it has;
unhealthy once its looks after the grace fail the declared number of times in a row, said with what the
check found. What the check found stays in the condition's evidence: its summary names the check, never a
path or an address.
- **The budget.** Ninety looks a minute on one machine — the default interval on the busiest machine the
research measured; above it the engine spaces its own looks out and says so.
- **The count.** `module check` warns of every long-running resource without `health`, prints the count, and
refuses one from 2026-11-18, six weeks after Phase A went live.
- **The proof.** The replay of issue 145 — a web server whose application accepts every request and never
answers — is said unhealthy by its http check in two looks while a tcp check connects, and the controller
raises the module on the second statement. Proved: it fails on the trunk before Phase B and passes on it.
**Phase C — the provider hold.** The provider a consumer's `needs` names is its recorded binding to data
([ADR 0232](../../02-DECISIONS/0232-a-binding-to-a-consumers-data-moves-only-by-a-person.md)), and
otherwise the machine its credential for the provision comes from and the module there that offers it.
Only a check's own finding is held — down or restarting is the consumer's. A provider is unhealthy on the
record when its condition is open or its machine's newest statement says so, so the order the machines'
statements arrive in does not matter. The gate has a word between a pass and a fault: *waiting*, which never
puts a build back at the bound. Proved by the test of rule 5 (one provider, three consumers on two
machines: one condition, urgent, listing all three; their gates wait; after recovery only the one still
failing is raised), which fails with four conditions when the hold is taken out.
**Phase D — the bed.** In mesh-lab's replays, which every merge check of a module of the graph already runs
from the lab's trunk with the runtime and the change's catalogue — so nothing else had to change for the
catalogue's check to start it. It proves the resources whose declared check or image the change touches
(every declared one when it cannot tell), each alone: its literal environment, the files its module writes
in full, an empty place for every other mount, no secret and no provider. A program that stays up while its
check does not see it fails the change; one that does not stay up alone is said and left to the first
machine's gate; a mesh-built image and a tool or unit check are said. The replay of the studio — a server
bound to the address its hostname names, and an image check asking the loopback — fails the bed, and passes
once the hostname is set to every address.
**Phase E — the migration.** The catalogue keeps the count in a file of its own, and its merge check fails
a change that raises it and one that lowers it without writing the new number. It starts at 93 long-running
resources. The first batch takes it to 70: the image checks of the seven modules that ship them, adopted where
they read healthy on the live mesh — except the mail antivirus, whose six-minute start is past the bound,
and the mail cache, whose image ships none — and tcp or http on endpoints four services already declare.
Still to do for these phases' "done when": each read on the live mesh once rolled out in order — the
node-engine, then the controller, then the catalogue's declarations; the count's first live reading; and
the bed's first run on a catalogue change at the build seat.
## What is not decided here
- Whether a healer restarts what stays unhealthy (its own record, under ADR 0231).