The release gate judged a module by what the mesh saw from outside. So a container that crash-looped after it applied passed it. With mesh-host#47, each machine now states the health of every long-running resource it runs for a module.
What changed:
Store: migration 0076-a-module-says-how-it-is-healthy, table node_health. It holds one row per machine: the newest statement (said_at from the machine's clock orders it, heard_at is ours), its resources, and per-module streaks of unhealthy statements. Inventory has HealthOf, Healths and RecordHealth. A statement older than the one kept is refused.
Link:
Report.Health and the types Health, ResourceHealth, HealthSaid, with a wire-names test matching mesh-host's.
The health event mesh.control.*.health is subscribed on core NATS beside the heartbeats, as KindHealth. The machine is taken from the subject, never the body.
Its contract is ordered by at, tested by TestAnOlderHealthStatementIsRefused.
Server.Hears(Healths) wires it up.
Conditions: a new scope, module. module.<module>.<machine>.unhealthy (kind module-unhealthy, source health, resolver self) is raised on the second statement in a row that says a resource of the module is unhealthy, or on any while it is already open. It is cleared on the first statement that does not say it. It is a warning, and urgent after 4 h. The summary is in words; the targets, streaks and since go in the evidence. A single statement is listed as unconfirmed in node show.
Gate (ADR 0236 §2 as amended):
For a catalogue module, a judging passes only when every long-running resource of the module on that machine is stated healthy in a statement heard since the send.
starting, unhealthy, held or unknown makes the judging not yet, so the build fails at the bound and is put back (§3).
Unreadable health is never read as healthy.
The module's own condition holds it, including for module names with dots.
node show lists each resource with its state, since when, its reason and the restarts counted. status shows the condition with the other conditions.
Writers table: the machine-report row also names mesh.control.*.health. The writer is the same (ownMachine), so no grant changed and there is nothing to mirror in mesh-host's genesis lock.
Compatibility: an engine that sends no health gets no row. Its machine's health is not known: the gate judges it as before, and nothing is raised or cleared for it.
Tests (rule 4):
TestTwoUnhealthyStatementsRaiseTheModulesConditionAndAHealthyOneClearsIt: one statement raises nothing and is listed unconfirmed; two raise; it is urgent after 4 h; a starting statement (the new build's start) clears it; the streak restarts after that.
TestAnOlderHealthStatementIsRefused
TestAReportWithNoHealthRaisesAndKeepsNothing
TestTheHealthDefinitions, extended for starting, unhealthy, a statement from before the send, another module's state, unreadable health, and the held condition.
TestAHealthEventIsKeptAsTheMachineInItsSubject
Replay:TestReplayCrashLoopFailsItsGateOnTheFirstMachine is written only with what main already had, so the prover can lay it over main. Proved: it fails on origin/main (the crash loop passes 3 judgings and is sent to the second machine) and passes here (it fails at the bound on the first machine and is put back to c1). Its engine half is mesh-lab R-crashloop.
Checks:
merge-check.sh passes under -race against a throwaway postgres:17, after rebasing on #104.
check-here: mesh/merge-gate PASS (4 of 4 compose), mesh/repo-check PASS.
Merge after mesh-host#47 is rolled out. Feature a-module-says-how-it-is-healthy.
**The release gate judged a module by what the mesh saw from outside.** So a container that crash-looped after it applied passed it. With mesh-host#47, each machine now states the health of every long-running resource it runs for a module.
**What changed:**
- **Store:** migration `0076-a-module-says-how-it-is-healthy`, table `node_health`. It holds one row per machine: the newest statement (`said_at` from the machine's clock orders it, `heard_at` is ours), its resources, and per-module streaks of unhealthy statements. Inventory has `HealthOf`, `Healths` and `RecordHealth`. A statement older than the one kept is refused.
- **Link:**
- `Report.Health` and the types `Health`, `ResourceHealth`, `HealthSaid`, with a wire-names test matching mesh-host's.
- The health event `mesh.control.*.health` is subscribed on core NATS beside the heartbeats, as `KindHealth`. The machine is taken from the subject, never the body.
- Its contract is ordered by `at`, tested by `TestAnOlderHealthStatementIsRefused`.
- `Server.Hears(Healths)` wires it up.
- **Conditions:** a new scope, `module`. `module.<module>.<machine>.unhealthy` (kind `module-unhealthy`, source `health`, resolver `self`) is raised on the **second** statement in a row that says a resource of the module is unhealthy, or on any while it is already open. It is cleared on the first statement that does not say it. It is a warning, and urgent after 4 h. The summary is in words; the targets, streaks and since go in the evidence. A single statement is listed as *unconfirmed* in `node show`.
- **Gate** (ADR 0236 §2 as amended):
- For a catalogue module, a judging passes only when every long-running resource of the module on that machine is stated `healthy` in a statement heard since the send.
- `starting`, `unhealthy`, `held` or `unknown` makes the judging *not yet*, so the build fails at the bound and is put back (§3).
- Unreadable health is never read as healthy.
- The module's own condition holds it, including for module names with dots.
- **`node show`** lists each resource with its state, since when, its reason and the restarts counted. **`status`** shows the condition with the other conditions.
- **Writers table:** the machine-report row also names `mesh.control.*.health`. The writer is the same (`ownMachine`), so no grant changed and there is nothing to mirror in mesh-host's genesis lock.
**Compatibility:** an engine that sends no `health` gets no row. Its machine's health is *not known*: the gate judges it as before, and nothing is raised or cleared for it.
**Tests** (rule 4):
- `TestTwoUnhealthyStatementsRaiseTheModulesConditionAndAHealthyOneClearsIt`: one statement raises nothing and is listed unconfirmed; two raise; it is urgent after 4 h; a `starting` statement (the new build's start) clears it; the streak restarts after that.
- `TestAnOlderHealthStatementIsRefused`
- `TestAReportWithNoHealthRaisesAndKeepsNothing`
- `TestTheHealthDefinitions`, extended for starting, unhealthy, a statement from before the send, another module's state, unreadable health, and the held condition.
- `TestAHealthEventIsKeptAsTheMachineInItsSubject`
- **Replay:** `TestReplayCrashLoopFailsItsGateOnTheFirstMachine` is written only with what main already had, so the prover can lay it over main. **Proved:** it fails on origin/main (the crash loop passes 3 judgings and is sent to the second machine) and passes here (it fails at the bound on the first machine and is put back to c1). Its engine half is mesh-lab R-crashloop.
**Checks:**
- `merge-check.sh` passes under `-race` against a throwaway postgres:17, after rebasing on #104.
- `check-here`: `mesh/merge-gate` PASS (4 of 4 compose), `mesh/repo-check` PASS.
**Merge after mesh-host#47 is rolled out.** Feature `a-module-says-how-it-is-healthy`.
mesh-controller on novox: passed — healthy 3 times over 3m39s
mesh-controller on the rest running it: sent
build-agent on ace: passed — healthy 3 times over 3m41s
build-agent on the rest running it: sent
route-proxy on ace: passed — healthy 3 times over 7m11s
route-proxy on the rest running it: sent
Transitions
2026-10-07 00:28 (new) → proposed (announced): novox/mesh-controller#107's head announced
2026-10-07 00:39 proposed → checked (checked): the verdict names this commit
2026-10-07 00:39 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-07 00:45 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-07 00:45 published → delivering (go): its walk started: let go by this owner in its group's order, by a person, or on the controller's own path
2026-10-07 01:05 delivering → delivered (done): its walk is done: every machine of its deploy plan passed, or was left as its policy says
The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-controller@725fcd977e75` — **delivered** since 2026-10-07T01:05:34Z
**Delivery plan** — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- tier 2: route-proxy
- ace: receives build-agent, route-proxy
- g14: receives build-agent
- novox: receives mesh-controller, build-agent, route-proxy
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- route-proxy provides route: its consumers are sent again after it
- route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
**Group** `feat/a-module-says-how-it-is-healthy`, in order: novox/hq@dea72dc4fc8c → novox/mesh-lab@5e3ae7b835b2
- novox/mesh-controller@725fcd977e75 before novox/mesh-host@1fc1e74cc3c9: built by
- novox/mesh-host@1fc1e74cc3c9 before novox/mesh-controller@725fcd977e75: engine before controller
**Machines**
- mesh-controller on novox: passed — healthy 3 times over 3m39s
- mesh-controller on the rest running it: sent
- build-agent on ace: passed — healthy 3 times over 3m41s
- build-agent on the rest running it: sent
- route-proxy on ace: passed — healthy 3 times over 7m11s
- route-proxy on the rest running it: sent
**Transitions**
- 2026-10-07 00:28 (new) → proposed (announced): novox/mesh-controller#107's head announced
- 2026-10-07 00:39 proposed → checked (checked): the verdict names this commit
- 2026-10-07 00:39 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-07 00:45 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-07 00:45 published → delivering (go): its walk started: let go by this owner in its group's order, by a person, or on the controller's own path
- 2026-10-07 01:05 delivering → delivered (done): its walk is done: every machine of its deploy plan passed, or was left as its policy says
The commit's note under `refs/notes/mesh-plan` keeps every transition: `git log --notes=mesh-plan`.
The gate judged a module by what the mesh saw from outside, so a container that
crash-looped after it applied passed it. Each machine's node-engine now states
the health of every long-running resource it runs; the controller keeps the
newest statement per machine, raises module.<module>.<machine>.unhealthy on the
second statement in a row, clears it on the first that does not say it, and the
gate passes a module only when every long-running resource of it is stated
healthy since the send. An engine that states nothing is judged as before.
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
route-proxy provides route: its consumers are sent again after it
route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
Run by the build seat on g14 as build-1791332873250572598 (builds --log build-1791332873250572598).
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 45 tool(s)
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-07T00:21:01Z says they run
composing every machine as the mesh is
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
composing every machine with the change
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
merge gate: PASS — every machine composes with the change as it did without (4 of 4 compose)
judged by controller development build against the facts of 2026-10-07T00:21:01Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 3 module(s) in 3 tier(s): build-agent, mesh-controller, route-proxy
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.036s
ok github.com/novox/mesh-controller/cmd/mesh-controller 177.555s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.009s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.016s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.009s
ok github.com/novox/mesh-controller/examples/route-proxy 1.188s
ok github.com/novox/mesh-controller/internal/artifacts 1.035s
ok github.com/novox/mesh-controller/internal/broker 2.452s
ok github.com/novox/mesh-controller/internal/builder 1.288s
ok github.com/novox/mesh-controller/internal/catalogue 3.888s
ok github.com/novox/mesh-controller/internal/conditions 1.979s
ok github.com/novox/mesh-controller/internal/envfile 1.026s
ok github.com/novox/mesh-controller/internal/facts 1.033s
ok github.com/novox/mesh-controller/internal/identity 6.780s
ok github.com/novox/mesh-controller/internal/inventory 96.864s
ok github.com/novox/mesh-controller/internal/lease 17.705s
ok github.com/novox/mesh-controller/internal/licences 6.008s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.007s
ok github.com/novox/mesh-controller/internal/link 49.706s
ok github.com/novox/mesh-controller/internal/lint 1.775s
ok github.com/novox/mesh-controller/internal/outward 1.044s
ok github.com/novox/mesh-controller/internal/overlay 1.024s
ok github.com/novox/mesh-controller/internal/secrets 1.428s
ok github.com/novox/mesh-controller/internal/store 4.312s
ok github.com/novox/mesh-controller/internal/testbus 1.187s
ok github.com/novox/mesh-controller/internal/token 1.032s
**Merge check** at `497e8f6a`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Change plan** — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- tier 2: route-proxy
- ace: receives build-agent, route-proxy
- g14: receives build-agent
- novox: receives mesh-controller, build-agent, route-proxy
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- route-proxy provides route: its consumers are sent again after it
- route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
Run by the build seat on g14 as `build-1791332873250572598` (`builds --log build-1791332873250572598`).
```
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 45 tool(s)
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-07T00:21:01Z says they run
composing every machine as the mesh is
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
composing every machine with the change
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
merge gate: PASS — every machine composes with the change as it did without (4 of 4 compose)
judged by controller development build against the facts of 2026-10-07T00:21:01Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 3 module(s) in 3 tier(s): build-agent, mesh-controller, route-proxy
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.036s
ok github.com/novox/mesh-controller/cmd/mesh-controller 177.555s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.009s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.016s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.009s
ok github.com/novox/mesh-controller/examples/route-proxy 1.188s
ok github.com/novox/mesh-controller/internal/artifacts 1.035s
ok github.com/novox/mesh-controller/internal/broker 2.452s
ok github.com/novox/mesh-controller/internal/builder 1.288s
ok github.com/novox/mesh-controller/internal/catalogue 3.888s
ok github.com/novox/mesh-controller/internal/conditions 1.979s
ok github.com/novox/mesh-controller/internal/envfile 1.026s
ok github.com/novox/mesh-controller/internal/facts 1.033s
ok github.com/novox/mesh-controller/internal/identity 6.780s
ok github.com/novox/mesh-controller/internal/inventory 96.864s
ok github.com/novox/mesh-controller/internal/lease 17.705s
ok github.com/novox/mesh-controller/internal/licences 6.008s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.007s
ok github.com/novox/mesh-controller/internal/link 49.706s
ok github.com/novox/mesh-controller/internal/lint 1.775s
ok github.com/novox/mesh-controller/internal/outward 1.044s
ok github.com/novox/mesh-controller/internal/overlay 1.024s
ok github.com/novox/mesh-controller/internal/secrets 1.428s
ok github.com/novox/mesh-controller/internal/store 4.312s
ok github.com/novox/mesh-controller/internal/testbus 1.187s
ok github.com/novox/mesh-controller/internal/token 1.032s
```
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
route-proxy provides route: its consumers are sent again after it
route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
Run by the build seat on shanks as build-1791332935599150419 (builds --log build-1791332935599150419).
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 45 tool(s)
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-07T00:21:01Z says they run
composing every machine as the mesh is
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
composing every machine with the change
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
merge gate: PASS — every machine composes with the change as it did without (4 of 4 compose)
judged by controller development build against the facts of 2026-10-07T00:21:01Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 3 module(s) in 3 tier(s): build-agent, mesh-controller, route-proxy
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.031s
ok github.com/novox/mesh-controller/cmd/mesh-controller 433.981s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.019s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.046s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.030s
ok github.com/novox/mesh-controller/examples/route-proxy 1.229s
ok github.com/novox/mesh-controller/internal/artifacts 1.065s
ok github.com/novox/mesh-controller/internal/broker 2.538s
ok github.com/novox/mesh-controller/internal/builder 1.517s
ok github.com/novox/mesh-controller/internal/catalogue 4.153s
ok github.com/novox/mesh-controller/internal/conditions 2.026s
ok github.com/novox/mesh-controller/internal/envfile 1.048s
ok github.com/novox/mesh-controller/internal/facts 1.074s
ok github.com/novox/mesh-controller/internal/identity 52.983s
ok github.com/novox/mesh-controller/internal/inventory 271.904s
ok github.com/novox/mesh-controller/internal/lease 17.699s
ok github.com/novox/mesh-controller/internal/licences 49.655s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.045s
ok github.com/novox/mesh-controller/internal/link 71.167s
ok github.com/novox/mesh-controller/internal/lint 1.886s
ok github.com/novox/mesh-controller/internal/outward 1.071s
ok github.com/novox/mesh-controller/internal/overlay 1.065s
ok github.com/novox/mesh-controller/internal/secrets 1.500s
ok github.com/novox/mesh-controller/internal/store 11.101s
ok github.com/novox/mesh-controller/internal/testbus 1.211s
ok github.com/novox/mesh-controller/internal/token 1.014s
**Merge check** at `725fcd97`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Change plan** — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- tier 2: route-proxy
- ace: receives build-agent, route-proxy
- g14: receives build-agent
- novox: receives mesh-controller, build-agent, route-proxy
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- route-proxy provides route: its consumers are sent again after it
- route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
Run by the build seat on shanks as `build-1791332935599150419` (`builds --log build-1791332935599150419`).
```
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 45 tool(s)
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-07T00:21:01Z says they run
composing every machine as the mesh is
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
composing every machine with the change
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
merge gate: PASS — every machine composes with the change as it did without (4 of 4 compose)
judged by controller development build against the facts of 2026-10-07T00:21:01Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 3 module(s) in 3 tier(s): build-agent, mesh-controller, route-proxy
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.031s
ok github.com/novox/mesh-controller/cmd/mesh-controller 433.981s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.019s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.046s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.030s
ok github.com/novox/mesh-controller/examples/route-proxy 1.229s
ok github.com/novox/mesh-controller/internal/artifacts 1.065s
ok github.com/novox/mesh-controller/internal/broker 2.538s
ok github.com/novox/mesh-controller/internal/builder 1.517s
ok github.com/novox/mesh-controller/internal/catalogue 4.153s
ok github.com/novox/mesh-controller/internal/conditions 2.026s
ok github.com/novox/mesh-controller/internal/envfile 1.048s
ok github.com/novox/mesh-controller/internal/facts 1.074s
ok github.com/novox/mesh-controller/internal/identity 52.983s
ok github.com/novox/mesh-controller/internal/inventory 271.904s
ok github.com/novox/mesh-controller/internal/lease 17.699s
ok github.com/novox/mesh-controller/internal/licences 49.655s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.045s
ok github.com/novox/mesh-controller/internal/link 71.167s
ok github.com/novox/mesh-controller/internal/lint 1.886s
ok github.com/novox/mesh-controller/internal/outward 1.071s
ok github.com/novox/mesh-controller/internal/overlay 1.065s
ok github.com/novox/mesh-controller/internal/secrets 1.500s
ok github.com/novox/mesh-controller/internal/store 11.101s
ok github.com/novox/mesh-controller/internal/testbus 1.211s
ok github.com/novox/mesh-controller/internal/token 1.014s
```
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The release gate judged a module by what the mesh saw from outside. So a container that crash-looped after it applied passed it. With mesh-host#47, each machine now states the health of every long-running resource it runs for a module.
What changed:
0076-a-module-says-how-it-is-healthy, tablenode_health. It holds one row per machine: the newest statement (said_atfrom the machine's clock orders it,heard_atis ours), its resources, and per-module streaks of unhealthy statements. Inventory hasHealthOf,HealthsandRecordHealth. A statement older than the one kept is refused.Report.Healthand the typesHealth,ResourceHealth,HealthSaid, with a wire-names test matching mesh-host's.mesh.control.*.healthis subscribed on core NATS beside the heartbeats, asKindHealth. The machine is taken from the subject, never the body.at, tested byTestAnOlderHealthStatementIsRefused.Server.Hears(Healths)wires it up.module.module.<module>.<machine>.unhealthy(kindmodule-unhealthy, sourcehealth, resolverself) is raised on the second statement in a row that says a resource of the module is unhealthy, or on any while it is already open. It is cleared on the first statement that does not say it. It is a warning, and urgent after 4 h. The summary is in words; the targets, streaks and since go in the evidence. A single statement is listed as unconfirmed innode show.healthyin a statement heard since the send.starting,unhealthy,heldorunknownmakes the judging not yet, so the build fails at the bound and is put back (§3).node showlists each resource with its state, since when, its reason and the restarts counted.statusshows the condition with the other conditions.mesh.control.*.health. The writer is the same (ownMachine), so no grant changed and there is nothing to mirror in mesh-host's genesis lock.Compatibility: an engine that sends no
healthgets no row. Its machine's health is not known: the gate judges it as before, and nothing is raised or cleared for it.Tests (rule 4):
TestTwoUnhealthyStatementsRaiseTheModulesConditionAndAHealthyOneClearsIt: one statement raises nothing and is listed unconfirmed; two raise; it is urgent after 4 h; astartingstatement (the new build's start) clears it; the streak restarts after that.TestAnOlderHealthStatementIsRefusedTestAReportWithNoHealthRaisesAndKeepsNothingTestTheHealthDefinitions, extended for starting, unhealthy, a statement from before the send, another module's state, unreadable health, and the held condition.TestAHealthEventIsKeptAsTheMachineInItsSubjectTestReplayCrashLoopFailsItsGateOnTheFirstMachineis written only with what main already had, so the prover can lay it over main. Proved: it fails on origin/main (the crash loop passes 3 judgings and is sent to the second machine) and passes here (it fails at the bound on the first machine and is put back to c1). Its engine half is mesh-lab R-crashloop.Checks:
merge-check.shpasses under-raceagainst a throwaway postgres:17, after rebasing on #104.check-here:mesh/merge-gatePASS (4 of 4 compose),mesh/repo-checkPASS.Merge after mesh-host#47 is rolled out. Feature
a-module-says-how-it-is-healthy.Delivery
novox/mesh-controller@725fcd977e75— delivered since 2026-10-07T01:05:34ZDelivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Group
feat/a-module-says-how-it-is-healthy, in order: novox/hq@dea72dc4fc → novox/mesh-lab@5e3ae7b835Machines
Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.497e8f6af7to725fcd977eMerge check at
497e8f6amesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)mesh/repo-check: PASS — its merge-check.sh passedChange plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Run by the build seat on g14 as
build-1791332873250572598(builds --log build-1791332873250572598).Merge check at
725fcd97mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)mesh/repo-check: PASS — its merge-check.sh passedChange plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Run by the build seat on shanks as
build-1791332935599150419(builds --log build-1791332935599150419).