A resource that says merge may carry takes-settings, a list of top-level setting keys (hq ADR 0326):
ApplySettings lays only the named keys over that file; an empty list takes none. The field is removed with merge and protected, so it never reaches the node-engine. On a file that does not merge it is refused rather than passed on.
UnusedSettings: for a module whose mergeable files all name their keys, a key lands in a mergeable file only when a file names it. Anything else not taken elsewhere is stray, and the message says which keys each file takes. A module none of whose files name keys keeps today's form, with nothing stray.
TakenSettingsProblems, run by the module check (ParseManifest) and by JudgeSettings, refuses: the field on a non-merging file, a value that is not a list, a key named twice, a mesh word, a protected key, and a module with one naming and one silent mergeable file.
Held back, as hq issue 574: ADR 0326 §3's refusal of a module that declares a setting and owns a silent mergeable file. betterbird is one, and the catalogue cannot name its keys before this controller runs. With the refusal in, this PR's catalogue check failed against catalogue main (first head 286257d).
hq issue 168. Every key of a module's layers merged into every mergeable file it owns: searxng's endpoints landed in its settings.yml, keycloak's issuer in its tools' config.json. So a module could not own two configurable files. ADR 0164 §11 decided that a setting names the files that read it. ADR 0326 spells that from the file's side, so the operator's own values stay declared nowhere (ADR 0262 §2).
How it was tested
New internal/catalogue/setting_takes_test.go covers a module with two mergeable files where each takes only its named keys, an empty list, today's form kept, a stray key, mixed naming refused, and every refusal of §4. Every settled file is also checked for the field's removal.
With the filter and the stray judgement disabled, TestEachMergeableFileTakesOnlyTheKeysItNames, TestAnEmptyListTakesNoSetting and TestAKeyNoFileNamesIsStray fail.
sh merge-check.sh passes locally. Store tests were skipped because there was no MESH_TEST_POSTGRES.
The catalogue tests (internal/catalogue, cmd/mesh-controller) were run with MESH_CHECK_BESIDE at catalogue main (cd2b6aa) and at mesh-catalog #252's head. Both pass, except TestTheResolvedPathRulesAreTheNodeEnginesOwn, which needs mesh-host beside and was not set up locally.
Order
This controller must finish its walk before mesh-catalog #252 (which adds takes-settings) merges. An older controller passes the field to the node-engine, which parses resources strictly.
Fixes issue 168.
## What
A resource that says `merge` may carry `takes-settings`, a list of top-level setting keys (hq ADR 0326):
- `ApplySettings` lays only the named keys over that file; an empty list takes none. The field is removed with `merge` and `protected`, so it never reaches the node-engine. On a file that does not merge it is refused rather than passed on.
- `UnusedSettings`: for a module whose mergeable files all name their keys, a key lands in a mergeable file only when a file names it. Anything else not taken elsewhere is stray, and the message says which keys each file takes. A module none of whose files name keys keeps today's form, with nothing stray.
- `TakenSettingsProblems`, run by the module check (`ParseManifest`) and by `JudgeSettings`, refuses: the field on a non-merging file, a value that is not a list, a key named twice, a mesh word, a protected key, and a module with one naming and one silent mergeable file.
- **Held back, as hq issue 574:** ADR 0326 §3's refusal of a module that declares a setting and owns a silent mergeable file. betterbird is one, and the catalogue cannot name its keys before this controller runs. With the refusal in, this PR's catalogue check failed against catalogue main (first head 286257d).
`declaration.go` is untouched (PR #262 changes it).
## Why
hq issue 168. Every key of a module's layers merged into every mergeable file it owns: searxng's `endpoints` landed in its `settings.yml`, keycloak's `issuer` in its tools' `config.json`. So a module could not own two configurable files. ADR 0164 §11 decided that a setting names the files that read it. ADR 0326 spells that from the file's side, so the operator's own values stay declared nowhere (ADR 0262 §2).
## How it was tested
- New `internal/catalogue/setting_takes_test.go` covers a module with two mergeable files where each takes only its named keys, an empty list, today's form kept, a stray key, mixed naming refused, and every refusal of §4. Every settled file is also checked for the field's removal.
- With the filter and the stray judgement disabled, `TestEachMergeableFileTakesOnlyTheKeysItNames`, `TestAnEmptyListTakesNoSetting` and `TestAKeyNoFileNamesIsStray` fail.
- `sh merge-check.sh` passes locally. Store tests were skipped because there was no `MESH_TEST_POSTGRES`.
- The catalogue tests (`internal/catalogue`, `cmd/mesh-controller`) were run with `MESH_CHECK_BESIDE` at catalogue main (cd2b6aa) and at mesh-catalog #252's head. Both pass, except `TestTheResolvedPathRulesAreTheNodeEnginesOwn`, which needs mesh-host beside and was not set up locally.
## Order
This controller must finish its walk before mesh-catalog #252 (which adds `takes-settings`) merges. An older controller passes the field to the node-engine, which parses resources strictly.
Fixes issue 168.
mesh/merge-gate pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without …
Every key of a module's layers merged into every mergeable file it owns:
the mesh's own words, a key meant for a ${setting:} in another file, a
key for a second configuration file. A module could not own two
configurable files. A file now names its keys in takes-settings and
takes only those; a key no file names is stray where it is set; a
module that declares a setting names the keys of every mergeable file,
and one that declares none keeps today's form (ADR 0164 §15).
Deliverynovox/mesh-controller@b5383970550b — delivered since 2026-10-12T22:14:58Z
Delivery plan — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
tier 0: mesh-controller
tier 1: build-agent
ace: receives build-agent
g14: receives build-agent
novox: receives mesh-controller, build-agent
shanks: receives build-agent
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent is judged on its first machine
Machines
mesh-controller on novox: passed — healthy 3 times over 3m38s
mesh-controller on the rest running it: sent
build-agent on g14: passed — healthy 1 times over 30s
build-agent on the rest running it: sent
Transitions
2026-10-12 16:01 (new) → proposed (announced): novox/mesh-controller#272's head announced
2026-10-12 16:08 proposed → checked (checked): the verdict names this commit
2026-10-12 16:08 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-12 21:15 ready → proposed (recheck): repo-check failed on TestTheSecondControllerWaitsAndTakesAHigherEpoch, a lease test this change (settings filter) does not touch; flake suspected, issue opened
2026-10-12 21:35 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
2026-10-12 21:35 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-12 21:36 ready → proposed (trunk moved): out of date: judged against trunk 961f2e82ea, the trunk is now e63af0df17f5; judged again on a recheck or when it is merged
2026-10-12 22:01 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
2026-10-12 22:01 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-12 22:07 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-12 22:07 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 — not a failed walk that carried a later commit for it, after which it waits for a walk of its own commit
2026-10-12 22:14 delivering → delivered (done): its walk is done, carrying its own commit: 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@b5383970550b` — **delivered** since 2026-10-12T22:14:58Z
**Delivery plan** — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- ace: receives build-agent
- g14: receives build-agent
- novox: receives mesh-controller, build-agent
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent is judged on its first machine
**Machines**
- mesh-controller on novox: passed — healthy 3 times over 3m38s
- mesh-controller on the rest running it: sent
- build-agent on g14: passed — healthy 1 times over 30s
- build-agent on the rest running it: sent
**Transitions**
- 2026-10-12 16:01 (new) → proposed (announced): novox/mesh-controller#272's head announced
- 2026-10-12 16:08 proposed → checked (checked): the verdict names this commit
- 2026-10-12 16:08 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-12 21:15 ready → proposed (recheck): repo-check failed on TestTheSecondControllerWaitsAndTakesAHigherEpoch, a lease test this change (settings filter) does not touch; flake suspected, issue opened
- 2026-10-12 21:35 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
- 2026-10-12 21:35 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-12 21:36 ready → proposed (trunk moved): out of date: judged against trunk 961f2e82ea1c, the trunk is now e63af0df17f5; judged again on a recheck or when it is merged
- 2026-10-12 22:01 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
- 2026-10-12 22:01 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-12 22:07 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-12 22:07 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 — not a failed walk that carried a later commit for it, after which it waits for a walk of its own commit
- 2026-10-12 22:14 delivering → delivered (done): its walk is done, carrying its own commit: 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/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)
mesh/repo-check: FAIL — its merge-check.sh failed: --- FAIL: TestModuleCheckPassesTheCatalogue (0.89s); and TestEveryCatalogueManifestParses, TestNoCatalogueManifestNamesAnInstallation, TestEveryCatalogueIdentityFitsWhatItRequires, TestEveryCatalogueManifestDeclaresWhatItMounts
Delivery plan — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
tier 0: mesh-controller
tier 1: build-agent
ace: receives build-agent
g14: receives build-agent
novox: receives mesh-controller, build-agent
shanks: receives build-agent
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent is judged on its first machine
read by no module's build: internal/catalogue/setting_takes_test.go
Run by the build seat on ace as build-1791820047075813566 (builds --log build-1791820047075813566).
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is left out of the rest of the mesh: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is left out of the rest of the mesh: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
notes on laptop:
+ places.data.owner
+ places.data.path
+ x
run `plan laptop --diff` to see what it changes, `push laptop` to send it
notes on laptop:
~ x
the layer it replaced is kept: settings show notes --node laptop --history
run `plan laptop --diff` to see what it changes, `push laptop` to send it
{
"places": {
"data": {
"owner": "1001:1001",
"path": "/srv/notes"
}
},
"x": 1
}
set by an unnamed account at a shell on Ace through settings at 2026-10-12 15:55
keycloak on anchor:
+ issuer
+ x
run `plan anchor --diff` to see what it changes, `push anchor` to send it
power on anchor:
+ lid
+ x
run `plan anchor --diff` to see what it changes, `push anchor` to send it
keycloak on anchor:
~ x
the layer it replaced is kept: settings show keycloak --node anchor --history
run `plan anchor --diff` to see what it changes, `push anchor` to send it
claude-code on laptop:
+ managed_settings.permissions.allow
run `plan laptop --diff` to see what it changes, `push laptop` to send it
claude-code on the whole mesh:
+ mcp_servers.listener.type
+ mcp_servers.listener.url
run `push --behind` to send it to the machines running it
{
"managed_settings": {
"permissions": {
"allow": [
"Bash"
]
}
}
}
set at the controller's terminal by an unnamed account at a shell on Ace at 2026-10-12 15:55
keycloak on anchor:
+ url
run `plan anchor --diff` to see what it changes, `push anchor` to send it
{
"url": "https://id.example"
}
set at the controller's terminal by an unnamed account at a shell on Ace at 2026-10-12 15:55
notifier on anchor:
+ font
run `plan anchor --diff` to see what it changes, `push anchor` to send it
sonarr on anchor:
+ pgid
+ puid
+ x
run `plan anchor --diff` to see what it changes, `push anchor` to send it
sonarr on anchor:
~ x
the layer it replaced is kept: settings show sonarr --node anchor --history
run `plan anchor --diff` to see what it changes, `push anchor` to send it
plan-tier: tier 0 built; sent 12 module(s) to anchor first in one send (m01, m02, m03, m04, m05, m06, m07, m08, m09, m10, m11, m12), the rest once its gate passes
plan-tier: m01 passed its gate on anchor (healthy 3 times over 0s); the rest are sent
plan-tier: tier 0 built; sent m01, m02, m03, m04, m05, m06, m07, m08, m09, m10, m11, m12 to laptop, one send each
plan-tier: done — novox/mesh-catalog at c2, 1 tier(s)
plan-tier: tier 0 built; sent 3 module(s) to anchor first in one send (app1, app2, node-tools), the rest once its gate passes
node-tools's build c2 failed its gate on anchor and was put back to c1: not healthy within -1s of its apply: raised since it was sent: machine.anchor.core-behind — anchor runs the node tools it was last sent, not yet reported applied, and no plan is rolling them out (its settle window runs to the gate's bound)
plan-tier: the send to anchor in tier 0 failed its gate: not healthy within -1s of its apply: raised since it was sent: machine.anchor.core-behind — anchor runs the node tools it was last sent, not yet reported applied, and no plan is rolling them out (its settle window runs to the gate's bound); app1 passed on its own and is kept; passed on their own and kept: app2; node-tools failed its gate on anchor in tier 0: not healthy within -1s of its apply: raised since it was sent: machine.anchor.core-behind — anchor runs the node tools it was last sent, not yet reported applied, and no plan is rolling them out (its settle window runs to the gate's bound); put back node-tools to c1 on anchor, in one send; none reported left as it was
plan-tier: tier 0 built; sent 3 module(s) to anchor first in one send (app1, app2, app3), the rest once its gate passes
app1's build c2 failed its gate on anchor and was put back to c1: not healthy within -1s of its apply: anchor as a whole: raised since it was sent: machine.anchor.disk-full — anchor's root file system is full
app2's build c2 failed its gate on anchor and was put back to c1: not healthy within -1s of its apply: anchor as a whole: raised since it was sent: machine.anchor.disk-full — anchor's root file system is full
app3's build c2 failed its gate on anchor and was put back to c1: not healthy within -1s of its apply: anchor as a whole: raised since it was sent: machine.anchor.disk-full — anchor's root file system is full
plan-tier: app1 failed its gate on anchor in tier 0: not healthy within -1s of its apply: anchor as a whole: raised since it was sent: machine.anchor.disk-full — anchor's root file system is full; app2 failed its gate on anchor in tier 0: not healthy within -1s of its apply: anchor as a whole: raised since it was sent: machine.anchor.disk-full — anchor's root file system is full; app3 failed its gate on anchor in tier 0: not healthy within -1s of its apply: anchor as a whole: raised since it was sent: machine.anchor.disk-full — anchor's root file system is full; put back app1 to c1, app2 to c1, app3 to c1 on anchor, in one send; none reported left as it was
plan-gate: tier 0 built; sent 1 module(s) to anchor first in one send (app), the rest once its gate passes
plan-gate: the send to anchor in tier 0 failed its gate: not healthy within -1s of its apply: anchor has not reported on what it was sent; app was left as it was — anchor already ran app c2, or a build identical to it, before the send, so nothing of it moved and nothing is put back
plan-gate: the send to anchor in tier 0 failed its gate: not healthy within -1s of its apply: anchor has not reported on what it was sent; app was left as it was — anchor already ran app c2, or a build identical to it, before the send, so nothing of it moved and nothing is put back; none reported left as it was
tier 0: plan-tier: tier 0 built; sent 2 module(s) to anchor first in one send (node-tools, app1), the rest once its gate passes
node-tools's build c2 failed its gate on anchor and was put back to c1: the witness on anchor judged the node-tools c2 and rolled-back: the node tools did not answer
plan-tier: put back at once: node-tools (the witness on anchor judged the node-tools c2 and rolled-back: the node tools did not answer); the rest of the send judged to their own verdicts
plan-tier: the send to anchor in tier 0 failed its gate: the witness on anchor judged the node-tools c2 and rolled-back: the node tools did not answer; node-tools was put back when it broke; passed on their own and kept: app1; none reported left as it was
plan-tier: tier 0 built; sent 2 module(s) to anchor first in one send (app1, node-tools), the rest once its gate passes
node-tools's build c2 failed its gate on anchor and was put back to c1: the witness on anchor judged the node-tools c2 and rolled-back: the node tools did not answer
plan-tier: put back at once: node-tools (the witness on anchor judged the node-tools c2 and rolled-back: the node tools did not answer); the rest of the send judged to their own verdicts
plan-tier: the send to anchor in tier 0 failed its gate: the witness on anchor judged the node-tools c2 and rolled-back: the node tools did not answer; app1 passed on its own and is kept; none reported left as it was
plan-tier: tier 0 built; sent 2 module(s) to anchor first in one send (node-tools, app1), the rest once its gate passes
plan-tier: node-tools passed its gate on anchor (healthy 3 times over 0s); the rest are sent
plan-tier: tier 0 built; sent node-tools, app1 to laptop, one send each
plan-tier: done — novox/mesh-catalog at c2, 1 tier(s)
plan-308-live (novox/mesh-catalog at c8c8c8c8) is let go by mesh-delivery; its first tier is asked at the next pass
plan-308-live stopped by a person at tier 0 of 1; what was asked still builds and registers, nothing further is asked or sent
this act by hand could NOT be recorded in the hand-act log, and is done anyway: the hand-act log mesh-controller_hand-acts is not on the bus — the controller asserts it at its start, so one older than this has not: nats: bucket not found
plan-308-stop stopped at tier 0 of 1; what was asked still builds and registers, nothing further is asked
this act by hand could NOT be recorded in the hand-act log, and is done anyway: the hand-act log mesh-controller_hand-acts is not on the bus — the controller asserts it at its start, so one older than this has not: nats: bucket not found
plan-308-close closed at tier 0 of 1; what was asked still builds and registers, nothing further is asked
tier 0: plan-308-retry retried at tier 0 of 2: asked a as build-1791820553111084734; the plan goes on from there as any plan does
this act by hand could NOT be recorded in the hand-act log, and is done anyway: the hand-act log mesh-controller_hand-acts is not on the bus — the controller asserts it at its start, so one older than this has not: nats: bucket not found
release-1791820553614538205: 2 build(s) wait for a gate on anchor, laptop; one machine at a time, each judged
release-1791820553614538205 releases it; `plans release-1791820553614538205` says where it is
build-1791820554061168266: could not build https://forge.example/novox/a.git:
cancelled by hand
plan-308-cancel: a failed to build in tier 0; the tiers after it are not asked
cancelled build-1791820554061168266 (https://forge.example/novox/a.git, waiting): deleted from the node-build-agent queue and recorded failed, cancelled by hand — a plan that asked for it fails with that
took the controller lease at epoch 1 (controller@Ace pid 2224 since 2026-10-12T15:51:58Z)
build-1791820554127987776: could not build https://forge.example/novox/a.git:
cancelled by hand
plan-308-clear: a failed to build in tier 0; the tiers after it are not asked
cancelled build-1791820554127987776 (https://forge.example/novox/a.git, waiting): deleted from the node-build-agent queue and recorded failed, cancelled by hand — a plan that asked for it fails with that
1 waiting ask(s) cancelled
gave the controller lease back (epoch 1)
tier 0: rebuild asked as build-1791820554684676235, joining plan-308-rebuild at tier 0 (novox/a at c0ffee): the plan takes this build as a's outcome; the plan had failed and builds again from this tier
the bus cannot be reached (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): what this does is not said, and is found by comparison
this act by hand could NOT be recorded in the hand-act log, and is done anyway: this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus
plan-308-again-plans: its end is kept and could NOT be said as plan-moved (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): the router holds what it touched until its bound
plan-308-again-plans stopped at tier 0 of 2; what was asked still builds and registers, nothing further is asked
the bus cannot be reached (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): what this does is not said, and is found by comparison
tier 0: plan-308-again-plans: its start is kept and could NOT be said as plan-moved (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): the router does not hold what it touches
plan-308-again-plans retried at tier 0 of 2: asked a as build-1791820555177145491; the plan goes on from there as any plan does
plan-308-again-plans: a failed to build in tier 0; the tiers after it are not asked
the bus cannot be reached (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): what this does is not said, and is found by comparison
this act by hand could NOT be recorded in the hand-act log, and is done anyway: this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus
plan-308-again-rebuild: its end is kept and could NOT be said as plan-moved (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): the router holds what it touched until its bound
plan-308-again-rebuild stopped at tier 0 of 2; what was asked still builds and registers, nothing further is asked
tier 0: plan-308-again-rebuild: its start is kept and could NOT be said as plan-moved (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): the router does not hold what it touches
rebuild asked as build-1791820555287912040, joining plan-308-again-rebuild at tier 0 (novox/a at c0ffee): the plan takes this build as a's outcome; the plan had failed and builds again from this tier
plan-308-again-rebuild: a failed to build in tier 0; the tiers after it are not asked
FAIL
FAIL github.com/novox/mesh-controller/cmd/mesh-controller 236.865s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.020s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.026s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.019s
ok github.com/novox/mesh-controller/examples/route-proxy 1.128s
ok github.com/novox/mesh-controller/internal/artifacts 1.072s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 3.904s
ok github.com/novox/mesh-controller/internal/builder 34.957s
--- FAIL: TestEveryCatalogueManifestParses (0.59s)
catalogue_check_test.go:26: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
catalogue_check_test.go:39: betterbird: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
catalogue_check_test.go:52: 127 manifests, 71 named endpoints, 30 routed endpoints resolved
--- FAIL: TestNoCatalogueManifestNamesAnInstallation (1.03s)
catalogue_check_test.go:62: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
catalogue_check_test.go:75: /var/lib/build-agent/workspace/check/mesh-catalog/modules/betterbird/module.json: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
--- FAIL: TestEveryCatalogueIdentityFitsWhatItRequires (0.04s)
catalogue_check_test.go:124: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
catalogue_check_test.go:137: /var/lib/build-agent/workspace/check/mesh-catalog/modules/betterbird/module.json: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
--- FAIL: TestEveryCatalogueManifestDeclaresWhatItMounts (0.47s)
mounts_test.go:75: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
mounts_test.go:85: betterbird: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
FAIL
FAIL github.com/novox/mesh-controller/internal/catalogue 5.831s
ok github.com/novox/mesh-controller/internal/conditions 2.584s
ok github.com/novox/mesh-controller/internal/envfile 1.066s
ok github.com/novox/mesh-controller/internal/facts 1.025s
ok github.com/novox/mesh-controller/internal/identity 4.232s
ok github.com/novox/mesh-controller/internal/inventory 89.565s
ok github.com/novox/mesh-controller/internal/lease 17.727s
ok github.com/novox/mesh-controller/internal/licences 3.853s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.067s
ok github.com/novox/mesh-controller/internal/link 60.235s
ok github.com/novox/mesh-controller/internal/lint 2.225s
ok github.com/novox/mesh-controller/internal/outward 1.057s
ok github.com/novox/mesh-controller/internal/overlay 1.052s
ok github.com/novox/mesh-controller/internal/secrets 1.431s
ok github.com/novox/mesh-controller/internal/store 3.322s
ok github.com/novox/mesh-controller/internal/testbus 1.213s
ok github.com/novox/mesh-controller/internal/token 1.017s
FAIL
--- what failed, picked from the whole of its output (the whole is in the build's log)
--- FAIL: TestModuleCheckPassesTheCatalogue (0.89s)
check_test.go:61: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
check_test.go:68: the catalogue does not pass its own check: 1 problem(s) in 127 manifest(s)
/var/lib/build-agent/workspace/check/mesh-catalog/modules/betterbird/module.json: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
adwaita: ok, 4 tool(s)
artifact-store-tools: ok, 4 tool(s), invokes seat:mesh-controller.artifacts, seat:mesh-controller.collect, mesh-catalog.catalog_modules, mesh-catalog.catalog_module
asus-zephyrus-g14: ok, 11 tool(s); WARNING: asusd, supergfxd, upower stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
audit-logger: ok, keeps trail (valuable), spool (valuable)
avahi: ok, 4 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
baserow: ok, keeps data (valuable), ready: server by its image's own check every 30s; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
blueman: ok, 3 tool(s)
bluetooth: ok, 9 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
build-agent: ok, keeps workspace (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
ca-trust: ok; WARNING: trust stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
claude-code: ok, 45 tool(s), keeps state servers, holdings, config, proposals, reads claude-licence-manager.bindings, keeps agent-home (valuable); WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
claude-licence-manager: ok, keeps state bindings, reads claude-code.holdings; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
clipmenu: ok, 3 tool(s)
confluence: ok
cups: ok, 7 tool(s); WARNING: socket, scheduler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
dbus: ok, 5 tool(s); WARNING: system-bus stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
de-spiegel: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
desk-channel: ok, 1 tool(s), invokes seat:node-notifier.send, keeps state shown; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
disk-load: ok, 4 tool(s)
distribution: ok, keeps registry (rebuildable); WARNING: store stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
dmenu: ok, 2 tool(s)
dnsmasq: ok, 3 tool(s), ready: service by unit every 30s; watch by its tool dnsmasq_health every 20s
docker: ok, 22 tool(s), invokes seat:mesh-controller.images; WARNING: socket, runtime, prune stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
docker-compose: ok, 9 tool(s)
dunst: ok, 6 tool(s)
fail2ban: ok, 1 tool(s); WARNING: run stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
FAIL github.com/novox/mesh-controller/cmd/mesh-controller 236.865s
--- FAIL: TestEveryCatalogueManifestParses (0.59s)
catalogue_check_test.go:26: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
catalogue_check_test.go:39: betterbird: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
catalogue_check_test.go:52: 127 manifests, 71 named endpoints, 30 routed endpoints resolved
--- FAIL: TestNoCatalogueManifestNamesAnInstallation (1.03s)
catalogue_check_test.go:62: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
catalogue_check_test.go:75: /var/lib/build-agent/workspace/check/mesh-catalog/modules/betterbird/module.json: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
--- FAIL: TestEveryCatalogueIdentityFitsWhatItRequires (0.04s)
catalogue_check_test.go:124: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
catalogue_check_test.go:137: /var/lib/build-agent/workspace/check/mesh-catalog/modules/betterbird/module.json: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
--- FAIL: TestEveryCatalogueManifestDeclaresWhatItMounts (0.47s)
mounts_test.go:75: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
mounts_test.go:85: betterbird: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
FAIL github.com/novox/mesh-controller/internal/catalogue 5.831s
**Merge check** at `286257d8`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)
- `mesh/repo-check`: **FAIL** — its merge-check.sh failed: --- FAIL: TestModuleCheckPassesTheCatalogue (0.89s); and TestEveryCatalogueManifestParses, TestNoCatalogueManifestNamesAnInstallation, TestEveryCatalogueIdentityFitsWhatItRequires, TestEveryCatalogueManifestDeclaresWhatItMounts
**Delivery plan** — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- ace: receives build-agent
- g14: receives build-agent
- novox: receives mesh-controller, build-agent
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent is judged on its first machine
- read by no module's build: internal/catalogue/setting_takes_test.go
Run by the build seat on ace as `build-1791820047075813566` (`builds --log build-1791820047075813566`).
```
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is left out of the rest of the mesh: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is left out of the rest of the mesh: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
anchor is not counted as on the network: it does not resolve: these assignments cannot be applied:
- rival-one and rival-two both claim "the-seat", and only one thing may hold it per node
notes on laptop:
+ places.data.owner
+ places.data.path
+ x
run `plan laptop --diff` to see what it changes, `push laptop` to send it
notes on laptop:
~ x
the layer it replaced is kept: settings show notes --node laptop --history
run `plan laptop --diff` to see what it changes, `push laptop` to send it
{
"places": {
"data": {
"owner": "1001:1001",
"path": "/srv/notes"
}
},
"x": 1
}
set by an unnamed account at a shell on Ace through settings at 2026-10-12 15:55
keycloak on anchor:
+ issuer
+ x
run `plan anchor --diff` to see what it changes, `push anchor` to send it
power on anchor:
+ lid
+ x
run `plan anchor --diff` to see what it changes, `push anchor` to send it
keycloak on anchor:
~ x
the layer it replaced is kept: settings show keycloak --node anchor --history
run `plan anchor --diff` to see what it changes, `push anchor` to send it
claude-code on laptop:
+ managed_settings.permissions.allow
run `plan laptop --diff` to see what it changes, `push laptop` to send it
claude-code on the whole mesh:
+ mcp_servers.listener.type
+ mcp_servers.listener.url
run `push --behind` to send it to the machines running it
{
"managed_settings": {
"permissions": {
"allow": [
"Bash"
]
}
}
}
set at the controller's terminal by an unnamed account at a shell on Ace at 2026-10-12 15:55
keycloak on anchor:
+ url
run `plan anchor --diff` to see what it changes, `push anchor` to send it
{
"url": "https://id.example"
}
set at the controller's terminal by an unnamed account at a shell on Ace at 2026-10-12 15:55
notifier on anchor:
+ font
run `plan anchor --diff` to see what it changes, `push anchor` to send it
sonarr on anchor:
+ pgid
+ puid
+ x
run `plan anchor --diff` to see what it changes, `push anchor` to send it
sonarr on anchor:
~ x
the layer it replaced is kept: settings show sonarr --node anchor --history
run `plan anchor --diff` to see what it changes, `push anchor` to send it
plan-tier: tier 0 built; sent 12 module(s) to anchor first in one send (m01, m02, m03, m04, m05, m06, m07, m08, m09, m10, m11, m12), the rest once its gate passes
plan-tier: m01 passed its gate on anchor (healthy 3 times over 0s); the rest are sent
plan-tier: tier 0 built; sent m01, m02, m03, m04, m05, m06, m07, m08, m09, m10, m11, m12 to laptop, one send each
plan-tier: done — novox/mesh-catalog at c2, 1 tier(s)
plan-tier: tier 0 built; sent 3 module(s) to anchor first in one send (app1, app2, node-tools), the rest once its gate passes
node-tools's build c2 failed its gate on anchor and was put back to c1: not healthy within -1s of its apply: raised since it was sent: machine.anchor.core-behind — anchor runs the node tools it was last sent, not yet reported applied, and no plan is rolling them out (its settle window runs to the gate's bound)
plan-tier: the send to anchor in tier 0 failed its gate: not healthy within -1s of its apply: raised since it was sent: machine.anchor.core-behind — anchor runs the node tools it was last sent, not yet reported applied, and no plan is rolling them out (its settle window runs to the gate's bound); app1 passed on its own and is kept; passed on their own and kept: app2; node-tools failed its gate on anchor in tier 0: not healthy within -1s of its apply: raised since it was sent: machine.anchor.core-behind — anchor runs the node tools it was last sent, not yet reported applied, and no plan is rolling them out (its settle window runs to the gate's bound); put back node-tools to c1 on anchor, in one send; none reported left as it was
plan-tier: tier 0 built; sent 3 module(s) to anchor first in one send (app1, app2, app3), the rest once its gate passes
app1's build c2 failed its gate on anchor and was put back to c1: not healthy within -1s of its apply: anchor as a whole: raised since it was sent: machine.anchor.disk-full — anchor's root file system is full
app2's build c2 failed its gate on anchor and was put back to c1: not healthy within -1s of its apply: anchor as a whole: raised since it was sent: machine.anchor.disk-full — anchor's root file system is full
app3's build c2 failed its gate on anchor and was put back to c1: not healthy within -1s of its apply: anchor as a whole: raised since it was sent: machine.anchor.disk-full — anchor's root file system is full
plan-tier: app1 failed its gate on anchor in tier 0: not healthy within -1s of its apply: anchor as a whole: raised since it was sent: machine.anchor.disk-full — anchor's root file system is full; app2 failed its gate on anchor in tier 0: not healthy within -1s of its apply: anchor as a whole: raised since it was sent: machine.anchor.disk-full — anchor's root file system is full; app3 failed its gate on anchor in tier 0: not healthy within -1s of its apply: anchor as a whole: raised since it was sent: machine.anchor.disk-full — anchor's root file system is full; put back app1 to c1, app2 to c1, app3 to c1 on anchor, in one send; none reported left as it was
plan-gate: tier 0 built; sent 1 module(s) to anchor first in one send (app), the rest once its gate passes
plan-gate: the send to anchor in tier 0 failed its gate: not healthy within -1s of its apply: anchor has not reported on what it was sent; app was left as it was — anchor already ran app c2, or a build identical to it, before the send, so nothing of it moved and nothing is put back
plan-gate: the send to anchor in tier 0 failed its gate: not healthy within -1s of its apply: anchor has not reported on what it was sent; app was left as it was — anchor already ran app c2, or a build identical to it, before the send, so nothing of it moved and nothing is put back; none reported left as it was
tier 0: plan-tier: tier 0 built; sent 2 module(s) to anchor first in one send (node-tools, app1), the rest once its gate passes
node-tools's build c2 failed its gate on anchor and was put back to c1: the witness on anchor judged the node-tools c2 and rolled-back: the node tools did not answer
plan-tier: put back at once: node-tools (the witness on anchor judged the node-tools c2 and rolled-back: the node tools did not answer); the rest of the send judged to their own verdicts
plan-tier: the send to anchor in tier 0 failed its gate: the witness on anchor judged the node-tools c2 and rolled-back: the node tools did not answer; node-tools was put back when it broke; passed on their own and kept: app1; none reported left as it was
plan-tier: tier 0 built; sent 2 module(s) to anchor first in one send (app1, node-tools), the rest once its gate passes
node-tools's build c2 failed its gate on anchor and was put back to c1: the witness on anchor judged the node-tools c2 and rolled-back: the node tools did not answer
plan-tier: put back at once: node-tools (the witness on anchor judged the node-tools c2 and rolled-back: the node tools did not answer); the rest of the send judged to their own verdicts
plan-tier: the send to anchor in tier 0 failed its gate: the witness on anchor judged the node-tools c2 and rolled-back: the node tools did not answer; app1 passed on its own and is kept; none reported left as it was
plan-tier: tier 0 built; sent 2 module(s) to anchor first in one send (node-tools, app1), the rest once its gate passes
plan-tier: node-tools passed its gate on anchor (healthy 3 times over 0s); the rest are sent
plan-tier: tier 0 built; sent node-tools, app1 to laptop, one send each
plan-tier: done — novox/mesh-catalog at c2, 1 tier(s)
plan-308-live (novox/mesh-catalog at c8c8c8c8) is let go by mesh-delivery; its first tier is asked at the next pass
plan-308-live stopped by a person at tier 0 of 1; what was asked still builds and registers, nothing further is asked or sent
this act by hand could NOT be recorded in the hand-act log, and is done anyway: the hand-act log mesh-controller_hand-acts is not on the bus — the controller asserts it at its start, so one older than this has not: nats: bucket not found
plan-308-stop stopped at tier 0 of 1; what was asked still builds and registers, nothing further is asked
this act by hand could NOT be recorded in the hand-act log, and is done anyway: the hand-act log mesh-controller_hand-acts is not on the bus — the controller asserts it at its start, so one older than this has not: nats: bucket not found
plan-308-close closed at tier 0 of 1; what was asked still builds and registers, nothing further is asked
tier 0: plan-308-retry retried at tier 0 of 2: asked a as build-1791820553111084734; the plan goes on from there as any plan does
this act by hand could NOT be recorded in the hand-act log, and is done anyway: the hand-act log mesh-controller_hand-acts is not on the bus — the controller asserts it at its start, so one older than this has not: nats: bucket not found
release-1791820553614538205: 2 build(s) wait for a gate on anchor, laptop; one machine at a time, each judged
release-1791820553614538205 releases it; `plans release-1791820553614538205` says where it is
build-1791820554061168266: could not build https://forge.example/novox/a.git:
cancelled by hand
plan-308-cancel: a failed to build in tier 0; the tiers after it are not asked
cancelled build-1791820554061168266 (https://forge.example/novox/a.git, waiting): deleted from the node-build-agent queue and recorded failed, cancelled by hand — a plan that asked for it fails with that
took the controller lease at epoch 1 (controller@Ace pid 2224 since 2026-10-12T15:51:58Z)
build-1791820554127987776: could not build https://forge.example/novox/a.git:
cancelled by hand
plan-308-clear: a failed to build in tier 0; the tiers after it are not asked
cancelled build-1791820554127987776 (https://forge.example/novox/a.git, waiting): deleted from the node-build-agent queue and recorded failed, cancelled by hand — a plan that asked for it fails with that
1 waiting ask(s) cancelled
gave the controller lease back (epoch 1)
tier 0: rebuild asked as build-1791820554684676235, joining plan-308-rebuild at tier 0 (novox/a at c0ffee): the plan takes this build as a's outcome; the plan had failed and builds again from this tier
the bus cannot be reached (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): what this does is not said, and is found by comparison
this act by hand could NOT be recorded in the hand-act log, and is done anyway: this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus
plan-308-again-plans: its end is kept and could NOT be said as plan-moved (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): the router holds what it touched until its bound
plan-308-again-plans stopped at tier 0 of 2; what was asked still builds and registers, nothing further is asked
the bus cannot be reached (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): what this does is not said, and is found by comparison
tier 0: plan-308-again-plans: its start is kept and could NOT be said as plan-moved (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): the router does not hold what it touches
plan-308-again-plans retried at tier 0 of 2: asked a as build-1791820555177145491; the plan goes on from there as any plan does
plan-308-again-plans: a failed to build in tier 0; the tiers after it are not asked
the bus cannot be reached (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): what this does is not said, and is found by comparison
this act by hand could NOT be recorded in the hand-act log, and is done anyway: this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus
plan-308-again-rebuild: its end is kept and could NOT be said as plan-moved (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): the router holds what it touched until its bound
plan-308-again-rebuild stopped at tier 0 of 2; what was asked still builds and registers, nothing further is asked
tier 0: plan-308-again-rebuild: its start is kept and could NOT be said as plan-moved (this control plane has no MESH_BUS_NATS, so it cannot reach the mesh's bus): the router does not hold what it touches
rebuild asked as build-1791820555287912040, joining plan-308-again-rebuild at tier 0 (novox/a at c0ffee): the plan takes this build as a's outcome; the plan had failed and builds again from this tier
plan-308-again-rebuild: a failed to build in tier 0; the tiers after it are not asked
FAIL
FAIL github.com/novox/mesh-controller/cmd/mesh-controller 236.865s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.020s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.026s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.019s
ok github.com/novox/mesh-controller/examples/route-proxy 1.128s
ok github.com/novox/mesh-controller/internal/artifacts 1.072s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 3.904s
ok github.com/novox/mesh-controller/internal/builder 34.957s
--- FAIL: TestEveryCatalogueManifestParses (0.59s)
catalogue_check_test.go:26: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
catalogue_check_test.go:39: betterbird: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
catalogue_check_test.go:52: 127 manifests, 71 named endpoints, 30 routed endpoints resolved
--- FAIL: TestNoCatalogueManifestNamesAnInstallation (1.03s)
catalogue_check_test.go:62: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
catalogue_check_test.go:75: /var/lib/build-agent/workspace/check/mesh-catalog/modules/betterbird/module.json: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
--- FAIL: TestEveryCatalogueIdentityFitsWhatItRequires (0.04s)
catalogue_check_test.go:124: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
catalogue_check_test.go:137: /var/lib/build-agent/workspace/check/mesh-catalog/modules/betterbird/module.json: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
--- FAIL: TestEveryCatalogueManifestDeclaresWhatItMounts (0.47s)
mounts_test.go:75: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
mounts_test.go:85: betterbird: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
FAIL
FAIL github.com/novox/mesh-controller/internal/catalogue 5.831s
ok github.com/novox/mesh-controller/internal/conditions 2.584s
ok github.com/novox/mesh-controller/internal/envfile 1.066s
ok github.com/novox/mesh-controller/internal/facts 1.025s
ok github.com/novox/mesh-controller/internal/identity 4.232s
ok github.com/novox/mesh-controller/internal/inventory 89.565s
ok github.com/novox/mesh-controller/internal/lease 17.727s
ok github.com/novox/mesh-controller/internal/licences 3.853s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.067s
ok github.com/novox/mesh-controller/internal/link 60.235s
ok github.com/novox/mesh-controller/internal/lint 2.225s
ok github.com/novox/mesh-controller/internal/outward 1.057s
ok github.com/novox/mesh-controller/internal/overlay 1.052s
ok github.com/novox/mesh-controller/internal/secrets 1.431s
ok github.com/novox/mesh-controller/internal/store 3.322s
ok github.com/novox/mesh-controller/internal/testbus 1.213s
ok github.com/novox/mesh-controller/internal/token 1.017s
FAIL
--- what failed, picked from the whole of its output (the whole is in the build's log)
--- FAIL: TestModuleCheckPassesTheCatalogue (0.89s)
check_test.go:61: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
check_test.go:68: the catalogue does not pass its own check: 1 problem(s) in 127 manifest(s)
/var/lib/build-agent/workspace/check/mesh-catalog/modules/betterbird/module.json: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
adwaita: ok, 4 tool(s)
artifact-store-tools: ok, 4 tool(s), invokes seat:mesh-controller.artifacts, seat:mesh-controller.collect, mesh-catalog.catalog_modules, mesh-catalog.catalog_module
asus-zephyrus-g14: ok, 11 tool(s); WARNING: asusd, supergfxd, upower stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
audit-logger: ok, keeps trail (valuable), spool (valuable)
avahi: ok, 4 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
baserow: ok, keeps data (valuable), ready: server by its image's own check every 30s; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
blueman: ok, 3 tool(s)
bluetooth: ok, 9 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
build-agent: ok, keeps workspace (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
ca-trust: ok; WARNING: trust stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
claude-code: ok, 45 tool(s), keeps state servers, holdings, config, proposals, reads claude-licence-manager.bindings, keeps agent-home (valuable); WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
claude-licence-manager: ok, keeps state bindings, reads claude-code.holdings; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
clipmenu: ok, 3 tool(s)
confluence: ok
cups: ok, 7 tool(s); WARNING: socket, scheduler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
dbus: ok, 5 tool(s); WARNING: system-bus stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
de-spiegel: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
desk-channel: ok, 1 tool(s), invokes seat:node-notifier.send, keeps state shown; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
disk-load: ok, 4 tool(s)
distribution: ok, keeps registry (rebuildable); WARNING: store stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
dmenu: ok, 2 tool(s)
dnsmasq: ok, 3 tool(s), ready: service by unit every 30s; watch by its tool dnsmasq_health every 20s
docker: ok, 22 tool(s), invokes seat:mesh-controller.images; WARNING: socket, runtime, prune stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
docker-compose: ok, 9 tool(s)
dunst: ok, 6 tool(s)
fail2ban: ok, 1 tool(s); WARNING: run stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
FAIL github.com/novox/mesh-controller/cmd/mesh-controller 236.865s
--- FAIL: TestEveryCatalogueManifestParses (0.59s)
catalogue_check_test.go:26: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
catalogue_check_test.go:39: betterbird: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
catalogue_check_test.go:52: 127 manifests, 71 named endpoints, 30 routed endpoints resolved
--- FAIL: TestNoCatalogueManifestNamesAnInstallation (1.03s)
catalogue_check_test.go:62: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
catalogue_check_test.go:75: /var/lib/build-agent/workspace/check/mesh-catalog/modules/betterbird/module.json: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
--- FAIL: TestEveryCatalogueIdentityFitsWhatItRequires (0.04s)
catalogue_check_test.go:124: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
catalogue_check_test.go:137: /var/lib/build-agent/workspace/check/mesh-catalog/modules/betterbird/module.json: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
--- FAIL: TestEveryCatalogueManifestDeclaresWhatItMounts (0.47s)
mounts_test.go:75: judged against /var/lib/build-agent/workspace/check/mesh-catalog as cloned beside this check
mounts_test.go:85: betterbird: this manifest cannot be used:
- betterbird declares settings, and its mergeable accounts names no takes-settings: a module that declares a setting names the keys each mergeable file takes, an empty list for none (novox/hq ADR 0326, ADR 0164 §11)
FAIL github.com/novox/mesh-controller/internal/catalogue 5.831s
```
mesh/merge-gate pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without …
betterbird declares a preference and owns a mergeable file that names no
keys, and the catalogue can only name them once this controller runs: the
refusal made the catalogue check fail against catalogue main. It follows
once mesh-catalog names the keys.
mesh/merge-gate head b5383970550b merged into trunk e63af0df17f5 — pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; every …
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)
mesh/repo-check: PASS — its merge-check.sh passed
Delivery plan — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
tier 0: mesh-controller
tier 1: build-agent
ace: receives build-agent
g14: receives build-agent
novox: receives mesh-controller, build-agent
shanks: receives build-agent
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent is judged on its first machine
read by no module's build: internal/catalogue/setting_takes_test.go
Run by the build seat on shanks as build-1791820872948188758 (builds --log build-1791820872948188758).
--- the gate: build-agent, mesh-controller
mesh-controller: ok, 58 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T15:55:47Z 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-12T15:55:47Z
modules the change moves:
- mesh-controller (changed)
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-delivery, 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 2 module(s) in 2 tier(s): build-agent, mesh-controller
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.038s
ok github.com/novox/mesh-controller/cmd/mesh-controller 264.171s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.035s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.046s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.029s
ok github.com/novox/mesh-controller/examples/route-proxy 1.189s
ok github.com/novox/mesh-controller/internal/artifacts 1.081s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 4.320s
ok github.com/novox/mesh-controller/internal/builder 37.538s
ok github.com/novox/mesh-controller/internal/catalogue 8.000s
ok github.com/novox/mesh-controller/internal/conditions 2.858s
ok github.com/novox/mesh-controller/internal/envfile 1.040s
ok github.com/novox/mesh-controller/internal/facts 1.041s
ok github.com/novox/mesh-controller/internal/identity 4.874s
ok github.com/novox/mesh-controller/internal/inventory 99.709s
ok github.com/novox/mesh-controller/internal/lease 17.700s
ok github.com/novox/mesh-controller/internal/licences 4.352s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.043s
ok github.com/novox/mesh-controller/internal/link 62.754s
ok github.com/novox/mesh-controller/internal/lint 2.464s
ok github.com/novox/mesh-controller/internal/outward 1.079s
ok github.com/novox/mesh-controller/internal/overlay 1.066s
ok github.com/novox/mesh-controller/internal/secrets 1.527s
ok github.com/novox/mesh-controller/internal/store 3.493s
ok github.com/novox/mesh-controller/internal/testbus 1.250s
ok github.com/novox/mesh-controller/internal/token 1.016s
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (0.41s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (0.43s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (0.42s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (0.42s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (0.41s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (0.38s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (0.44s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.30s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (0.46s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (0.56s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (0.41s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (0.41s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (0.47s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.42s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (0.46s)
./cmd/mesh-controller --- PASS: TestReplay237 (0.41s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (0.40s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (0.40s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (0.40s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (0.44s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.26s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.26s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.27s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.26s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.25s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.25s)
**Merge check** at `b5383970`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Delivery plan** — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- ace: receives build-agent
- g14: receives build-agent
- novox: receives mesh-controller, build-agent
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent is judged on its first machine
- read by no module's build: internal/catalogue/setting_takes_test.go
Run by the build seat on shanks as `build-1791820872948188758` (`builds --log build-1791820872948188758`).
```
--- the gate: build-agent, mesh-controller
mesh-controller: ok, 58 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T15:55:47Z 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-12T15:55:47Z
modules the change moves:
- mesh-controller (changed)
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-delivery, 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 2 module(s) in 2 tier(s): build-agent, mesh-controller
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.038s
ok github.com/novox/mesh-controller/cmd/mesh-controller 264.171s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.035s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.046s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.029s
ok github.com/novox/mesh-controller/examples/route-proxy 1.189s
ok github.com/novox/mesh-controller/internal/artifacts 1.081s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 4.320s
ok github.com/novox/mesh-controller/internal/builder 37.538s
ok github.com/novox/mesh-controller/internal/catalogue 8.000s
ok github.com/novox/mesh-controller/internal/conditions 2.858s
ok github.com/novox/mesh-controller/internal/envfile 1.040s
ok github.com/novox/mesh-controller/internal/facts 1.041s
ok github.com/novox/mesh-controller/internal/identity 4.874s
ok github.com/novox/mesh-controller/internal/inventory 99.709s
ok github.com/novox/mesh-controller/internal/lease 17.700s
ok github.com/novox/mesh-controller/internal/licences 4.352s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.043s
ok github.com/novox/mesh-controller/internal/link 62.754s
ok github.com/novox/mesh-controller/internal/lint 2.464s
ok github.com/novox/mesh-controller/internal/outward 1.079s
ok github.com/novox/mesh-controller/internal/overlay 1.066s
ok github.com/novox/mesh-controller/internal/secrets 1.527s
ok github.com/novox/mesh-controller/internal/store 3.493s
ok github.com/novox/mesh-controller/internal/testbus 1.250s
ok github.com/novox/mesh-controller/internal/token 1.016s
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (0.41s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (0.43s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (0.42s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (0.42s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (0.41s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (0.38s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (0.44s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.30s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (0.46s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (0.56s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (0.41s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (0.41s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (0.47s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.42s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (0.46s)
./cmd/mesh-controller --- PASS: TestReplay237 (0.41s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (0.40s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (0.40s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (0.40s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (0.44s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.26s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.26s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.27s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.26s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.25s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.25s)
```
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)
mesh/repo-check: PASS — its merge-check.sh passed
Delivery plan — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
tier 0: mesh-controller
tier 1: build-agent
ace: receives build-agent
g14: receives build-agent
novox: receives mesh-controller, build-agent
shanks: receives build-agent
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent is judged on its first machine
read by no module's build: internal/catalogue/setting_takes_test.go
Run by the build seat on g14 as build-1791820842516900020 (builds --log build-1791820842516900020).
--- the gate: build-agent, mesh-controller
mesh-controller: ok, 58 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T15:55:47Z 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-12T15:55:47Z
modules the change moves:
- mesh-controller (changed)
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-delivery, 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 2 module(s) in 2 tier(s): build-agent, mesh-controller
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.042s
ok github.com/novox/mesh-controller/cmd/mesh-controller 270.324s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.016s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.026s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.016s
ok github.com/novox/mesh-controller/examples/route-proxy 1.177s
ok github.com/novox/mesh-controller/internal/artifacts 1.050s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 8.273s
ok github.com/novox/mesh-controller/internal/builder 35.355s
ok github.com/novox/mesh-controller/internal/catalogue 8.402s
ok github.com/novox/mesh-controller/internal/conditions 5.254s
ok github.com/novox/mesh-controller/internal/envfile 1.037s
ok github.com/novox/mesh-controller/internal/facts 1.028s
ok github.com/novox/mesh-controller/internal/identity 9.729s
ok github.com/novox/mesh-controller/internal/inventory 91.301s
ok github.com/novox/mesh-controller/internal/lease 18.592s
ok github.com/novox/mesh-controller/internal/licences 9.265s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.008s
ok github.com/novox/mesh-controller/internal/link 62.759s
ok github.com/novox/mesh-controller/internal/lint 2.046s
ok github.com/novox/mesh-controller/internal/outward 1.029s
ok github.com/novox/mesh-controller/internal/overlay 1.022s
ok github.com/novox/mesh-controller/internal/secrets 1.319s
ok github.com/novox/mesh-controller/internal/store 7.655s
ok github.com/novox/mesh-controller/internal/testbus 1.164s
ok github.com/novox/mesh-controller/internal/token 1.012s
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (0.39s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (0.40s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (0.97s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (0.36s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (0.34s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (0.32s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (0.91s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.26s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (0.73s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (0.43s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (0.47s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (0.47s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (0.41s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.42s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (0.39s)
./cmd/mesh-controller --- PASS: TestReplay237 (0.34s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (0.37s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (0.35s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (0.37s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (0.38s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.21s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.23s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.23s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.22s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.20s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.22s)
**Merge check** at `dd108892`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Delivery plan** — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- ace: receives build-agent
- g14: receives build-agent
- novox: receives mesh-controller, build-agent
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent is judged on its first machine
- read by no module's build: internal/catalogue/setting_takes_test.go
Run by the build seat on g14 as `build-1791820842516900020` (`builds --log build-1791820842516900020`).
```
--- the gate: build-agent, mesh-controller
mesh-controller: ok, 58 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T15:55:47Z 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-12T15:55:47Z
modules the change moves:
- mesh-controller (changed)
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-delivery, 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 2 module(s) in 2 tier(s): build-agent, mesh-controller
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.042s
ok github.com/novox/mesh-controller/cmd/mesh-controller 270.324s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.016s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.026s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.016s
ok github.com/novox/mesh-controller/examples/route-proxy 1.177s
ok github.com/novox/mesh-controller/internal/artifacts 1.050s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 8.273s
ok github.com/novox/mesh-controller/internal/builder 35.355s
ok github.com/novox/mesh-controller/internal/catalogue 8.402s
ok github.com/novox/mesh-controller/internal/conditions 5.254s
ok github.com/novox/mesh-controller/internal/envfile 1.037s
ok github.com/novox/mesh-controller/internal/facts 1.028s
ok github.com/novox/mesh-controller/internal/identity 9.729s
ok github.com/novox/mesh-controller/internal/inventory 91.301s
ok github.com/novox/mesh-controller/internal/lease 18.592s
ok github.com/novox/mesh-controller/internal/licences 9.265s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.008s
ok github.com/novox/mesh-controller/internal/link 62.759s
ok github.com/novox/mesh-controller/internal/lint 2.046s
ok github.com/novox/mesh-controller/internal/outward 1.029s
ok github.com/novox/mesh-controller/internal/overlay 1.022s
ok github.com/novox/mesh-controller/internal/secrets 1.319s
ok github.com/novox/mesh-controller/internal/store 7.655s
ok github.com/novox/mesh-controller/internal/testbus 1.164s
ok github.com/novox/mesh-controller/internal/token 1.012s
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (0.39s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (0.40s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (0.97s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (0.36s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (0.34s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (0.32s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (0.91s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.26s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (0.73s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (0.43s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (0.47s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (0.47s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (0.41s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.42s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (0.39s)
./cmd/mesh-controller --- PASS: TestReplay237 (0.34s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (0.37s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (0.35s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (0.37s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (0.38s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.21s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.23s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.23s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.22s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.20s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.22s)
```
Independent review for hq issue 168 against ADR 0326 (read whole with knowledge-base.get 326), ADR 0164 and ADR 0262.
Clause by clause
§1: ApplySettings filters each layer to the named keys (onlyTaken) before merging. An empty list takes none. The default layer is still skipped in settle.
§2: takenSettingsProblems names every silent mergeable file once one file names its keys. It runs in ParseManifest (module check and registration) and in JudgeSettings (a stored definition being composed).
§3: the today's-form half is built. UnusedSettings returns nothing for a module with a silent mergeable file, and namesItsKeys is false. The refusal half (a module that declares a setting must name its files' keys) is held back to issue 574. I think holding it back is sound and safe. With the refusal in, the controller's own catalogue check fails against catalogue main because betterbird declares prefs. The catalogue cannot name betterbird's keys before a controller that strips the field runs, because #252's gate shows the node-engine refuses it. Without the refusal, betterbird composes exactly as today, so nothing live changes. The only gap is a new declaring module with a silent mergeable file registering between this merge and issue 574; the window is small, and 574 keeps the code and the test from 286257d. Its clause-7 test goes with it, so clause 7 is complete only once 574 lands.
§4: the field is refused on a file that does not merge (also in ApplySettings, for a stored definition). It is refused when it is not a list, names one of the seven mesh words, names a protected key, names a key twice, or names an unusable key.
§5: a named key lands; an unnamed key is stray, and the message says which keys each file takes.
§6: delete(out, TakesSettingsField) in ApplySettings, and a non-merging file carrying the field is refused, so the field never reaches a declaration.
No live change
I fetched the facts snapshot of 16:04Z and composed every machine (4 of 4) with controller main and with this head in throwaway stores. I did it twice: once with the stored definitions, and once with every definition of mesh-catalog main 23ea0f4 and mesh-media-catalog main 94b80fb laid over them (49 modules moved). In both runs the two declarations are byte-identical once fresh secret material is normalised. Every raw difference was a sealed value, a minted secret, a bcrypt hash or a WireGuard key that each throwaway store mints anew. No problems, nothing left out, and no definition on either main carries takes-settings.
Stripping
I composed the same snapshot with #252 merged into catalogue main. Controller main sends takes-settings and refuses exactly 3 resources: betterbird.accounts, keycloak.runtime-config and searxng.settings, with the node-engine's error "a file does not use takes-settings". This head composes all 4 machines with no problem, and the field appears 0 times.
Tests
I put main's settings.go and manifest.go under the new tests, and 5 of the 7 tests fail. TestAFileThatNamesNothingKeepsTodaysForm is the regression guard and passes either way, as it should. TestASoftwareSpelledKeyIsUsable tests the new file alone, so it also passes. I removed only the delete line: the strip assertion fails. I removed only the onlyTaken call: the filter tests fail. merge-check.sh with a throwaway PostgreSQL 18 exits 0: gofmt, go vet, go test -race, and the store tests ran with nothing skipped.
Statuses at this head
mesh/merge-gate success (4 of 4 machines compose as they did), mesh/repo-check success, mesh/delivery ready.
Order: merge this, wait until mesh-controller.plans says done, then mesh-catalog #252, then issue 574.
Verdict: approve at b5383970550b51403824a0e8200ca5a50003dc0c
Independent review for hq issue 168 against ADR 0326 (read whole with knowledge-base.get 326), ADR 0164 and ADR 0262.
1. Clause by clause
- §1: ApplySettings filters each layer to the named keys (onlyTaken) before merging. An empty list takes none. The default layer is still skipped in settle.
- §2: takenSettingsProblems names every silent mergeable file once one file names its keys. It runs in ParseManifest (module check and registration) and in JudgeSettings (a stored definition being composed).
- §3: the today's-form half is built. UnusedSettings returns nothing for a module with a silent mergeable file, and namesItsKeys is false. The refusal half (a module that declares a setting must name its files' keys) is held back to issue 574. I think holding it back is sound and safe. With the refusal in, the controller's own catalogue check fails against catalogue main because betterbird declares `prefs`. The catalogue cannot name betterbird's keys before a controller that strips the field runs, because #252's gate shows the node-engine refuses it. Without the refusal, betterbird composes exactly as today, so nothing live changes. The only gap is a new declaring module with a silent mergeable file registering between this merge and issue 574; the window is small, and 574 keeps the code and the test from 286257d. Its clause-7 test goes with it, so clause 7 is complete only once 574 lands.
- §4: the field is refused on a file that does not merge (also in ApplySettings, for a stored definition). It is refused when it is not a list, names one of the seven mesh words, names a protected key, names a key twice, or names an unusable key.
- §5: a named key lands; an unnamed key is stray, and the message says which keys each file takes.
- §6: delete(out, TakesSettingsField) in ApplySettings, and a non-merging file carrying the field is refused, so the field never reaches a declaration.
2. No live change
I fetched the facts snapshot of 16:04Z and composed every machine (4 of 4) with controller main and with this head in throwaway stores. I did it twice: once with the stored definitions, and once with every definition of mesh-catalog main 23ea0f4 and mesh-media-catalog main 94b80fb laid over them (49 modules moved). In both runs the two declarations are byte-identical once fresh secret material is normalised. Every raw difference was a sealed value, a minted secret, a bcrypt hash or a WireGuard key that each throwaway store mints anew. No problems, nothing left out, and no definition on either main carries takes-settings.
3. Stripping
I composed the same snapshot with #252 merged into catalogue main. Controller main sends takes-settings and refuses exactly 3 resources: betterbird.accounts, keycloak.runtime-config and searxng.settings, with the node-engine's error "a file does not use takes-settings". This head composes all 4 machines with no problem, and the field appears 0 times.
5. Tests
I put main's settings.go and manifest.go under the new tests, and 5 of the 7 tests fail. TestAFileThatNamesNothingKeepsTodaysForm is the regression guard and passes either way, as it should. TestASoftwareSpelledKeyIsUsable tests the new file alone, so it also passes. I removed only the delete line: the strip assertion fails. I removed only the onlyTaken call: the filter tests fail. merge-check.sh with a throwaway PostgreSQL 18 exits 0: gofmt, go vet, go test -race, and the store tests ran with nothing skipped.
6. Statuses at this head
mesh/merge-gate success (4 of 4 machines compose as they did), mesh/repo-check success, mesh/delivery ready.
Order: merge this, wait until mesh-controller.plans says done, then mesh-catalog #252, then issue 574.
Merge check at b5383970
Judged: head b5383970550b merged into trunk 2f157148c6c8; read beside it: mesh-catalog 9c9a76d220f8, mesh-controller-main 2f157148c6c8, mesh-host d8e785bb4b4b, mesh-tools 954e1a53eef9
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)
mesh/repo-check: FAIL — its merge-check.sh failed: --- FAIL: TestTheSecondControllerWaitsAndTakesAHigherEpochOnHandover (4.06s)
Delivery plan — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
tier 0: mesh-controller
tier 1: build-agent
ace: receives build-agent
g14: receives build-agent
novox: receives mesh-controller, build-agent
shanks: receives build-agent
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent is judged on its first machine
read by no module's build: internal/catalogue/setting_takes_test.go
Run by the build seat on g14 as build-1791838332100947375 (builds --log build-1791838332100947375).
--- the gate: build-agent, mesh-controller
mesh-controller: ok, 58 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T20:48:25Z 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-12T20:48:25Z
modules the change moves:
- mesh-controller (changed)
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-delivery, 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 2 module(s) in 2 tier(s): build-agent, mesh-controller
notes:
- internal/catalogue/setting_takes_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.032s
ok github.com/novox/mesh-controller/cmd/mesh-controller 287.332s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.012s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.021s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.018s
ok github.com/novox/mesh-controller/examples/route-proxy 1.191s
ok github.com/novox/mesh-controller/internal/artifacts 1.056s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 6.679s
ok github.com/novox/mesh-controller/internal/builder 38.864s
ok github.com/novox/mesh-controller/internal/catalogue 8.124s
ok github.com/novox/mesh-controller/internal/conditions 5.609s
ok github.com/novox/mesh-controller/internal/envfile 1.026s
ok github.com/novox/mesh-controller/internal/facts 1.035s
ok github.com/novox/mesh-controller/internal/identity 8.119s
ok github.com/novox/mesh-controller/internal/inventory 103.068s
--- FAIL: TestTheSecondControllerWaitsAndTakesAHigherEpochOnHandover (4.06s)
lease_test.go:71: a: took the controller lease at epoch 1 (a)
lease_test.go:71: b: another controller holds the lease (a, epoch 1, taken 2026-10-12T20:55:55Z); waiting until it lets go or stops renewing
lease_test.go:71: a: LOST the controller lease (epoch 1): the renewal could not be made: context deadline exceeded — this controller stops acting at once
lease_test.go:118: a, holding, answers 0, this controller does not hold the lease: it lost it — the renewal could not be made: context deadline exceeded
lease_test.go:86: taking: context canceled
FAIL
FAIL github.com/novox/mesh-controller/internal/lease 16.664s
ok github.com/novox/mesh-controller/internal/licences 7.739s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.006s
ok github.com/novox/mesh-controller/internal/link 66.179s
ok github.com/novox/mesh-controller/internal/lint 2.023s
ok github.com/novox/mesh-controller/internal/outward 1.029s
ok github.com/novox/mesh-controller/internal/overlay 1.023s
ok github.com/novox/mesh-controller/internal/secrets 1.331s
ok github.com/novox/mesh-controller/internal/store 5.987s
ok github.com/novox/mesh-controller/internal/testbus 1.163s
ok github.com/novox/mesh-controller/internal/token 1.013s
FAIL
--- what failed, picked from the whole of its output (the whole is in the build's log)
--- FAIL: TestTheSecondControllerWaitsAndTakesAHigherEpochOnHandover (4.06s)
lease_test.go:71: a: took the controller lease at epoch 1 (a)
lease_test.go:71: b: another controller holds the lease (a, epoch 1, taken 2026-10-12T20:55:55Z); waiting until it lets go or stops renewing
lease_test.go:71: a: LOST the controller lease (epoch 1): the renewal could not be made: context deadline exceeded — this controller stops acting at once
lease_test.go:118: a, holding, answers 0, this controller does not hold the lease: it lost it — the renewal could not be made: context deadline exceeded
lease_test.go:86: taking: context canceled
FAIL github.com/novox/mesh-controller/internal/lease 16.664s
**Merge check** at `b5383970`
Judged: head `b5383970550b` merged into trunk `2f157148c6c8`; read beside it: mesh-catalog `9c9a76d220f8`, mesh-controller-main `2f157148c6c8`, mesh-host `d8e785bb4b4b`, mesh-tools `954e1a53eef9`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)
- `mesh/repo-check`: **FAIL** — its merge-check.sh failed: --- FAIL: TestTheSecondControllerWaitsAndTakesAHigherEpochOnHandover (4.06s)
**Delivery plan** — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- ace: receives build-agent
- g14: receives build-agent
- novox: receives mesh-controller, build-agent
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent is judged on its first machine
- read by no module's build: internal/catalogue/setting_takes_test.go
Run by the build seat on g14 as `build-1791838332100947375` (`builds --log build-1791838332100947375`).
```
--- the gate: build-agent, mesh-controller
mesh-controller: ok, 58 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T20:48:25Z 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-12T20:48:25Z
modules the change moves:
- mesh-controller (changed)
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-delivery, 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 2 module(s) in 2 tier(s): build-agent, mesh-controller
notes:
- internal/catalogue/setting_takes_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.032s
ok github.com/novox/mesh-controller/cmd/mesh-controller 287.332s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.012s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.021s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.018s
ok github.com/novox/mesh-controller/examples/route-proxy 1.191s
ok github.com/novox/mesh-controller/internal/artifacts 1.056s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 6.679s
ok github.com/novox/mesh-controller/internal/builder 38.864s
ok github.com/novox/mesh-controller/internal/catalogue 8.124s
ok github.com/novox/mesh-controller/internal/conditions 5.609s
ok github.com/novox/mesh-controller/internal/envfile 1.026s
ok github.com/novox/mesh-controller/internal/facts 1.035s
ok github.com/novox/mesh-controller/internal/identity 8.119s
ok github.com/novox/mesh-controller/internal/inventory 103.068s
--- FAIL: TestTheSecondControllerWaitsAndTakesAHigherEpochOnHandover (4.06s)
lease_test.go:71: a: took the controller lease at epoch 1 (a)
lease_test.go:71: b: another controller holds the lease (a, epoch 1, taken 2026-10-12T20:55:55Z); waiting until it lets go or stops renewing
lease_test.go:71: a: LOST the controller lease (epoch 1): the renewal could not be made: context deadline exceeded — this controller stops acting at once
lease_test.go:118: a, holding, answers 0, this controller does not hold the lease: it lost it — the renewal could not be made: context deadline exceeded
lease_test.go:86: taking: context canceled
FAIL
FAIL github.com/novox/mesh-controller/internal/lease 16.664s
ok github.com/novox/mesh-controller/internal/licences 7.739s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.006s
ok github.com/novox/mesh-controller/internal/link 66.179s
ok github.com/novox/mesh-controller/internal/lint 2.023s
ok github.com/novox/mesh-controller/internal/outward 1.029s
ok github.com/novox/mesh-controller/internal/overlay 1.023s
ok github.com/novox/mesh-controller/internal/secrets 1.331s
ok github.com/novox/mesh-controller/internal/store 5.987s
ok github.com/novox/mesh-controller/internal/testbus 1.163s
ok github.com/novox/mesh-controller/internal/token 1.013s
FAIL
--- what failed, picked from the whole of its output (the whole is in the build's log)
--- FAIL: TestTheSecondControllerWaitsAndTakesAHigherEpochOnHandover (4.06s)
lease_test.go:71: a: took the controller lease at epoch 1 (a)
lease_test.go:71: b: another controller holds the lease (a, epoch 1, taken 2026-10-12T20:55:55Z); waiting until it lets go or stops renewing
lease_test.go:71: a: LOST the controller lease (epoch 1): the renewal could not be made: context deadline exceeded — this controller stops acting at once
lease_test.go:118: a, holding, answers 0, this controller does not hold the lease: it lost it — the renewal could not be made: context deadline exceeded
lease_test.go:86: taking: context canceled
FAIL github.com/novox/mesh-controller/internal/lease 16.664s
```
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
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent, route-proxy is judged on its first machine
Run by the build seat on ace as build-1791839749749700026 (builds --log build-1791839749749700026).
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 58 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T21:08:25Z 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-12T21:08:25Z
modules the change moves:
- mesh-controller (changed)
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-delivery, 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 2 module(s) in 2 tier(s): build-agent, mesh-controller
notes:
- internal/catalogue/setting_takes_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.038s
ok github.com/novox/mesh-controller/cmd/mesh-controller 253.907s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.026s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.030s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.025s
ok github.com/novox/mesh-controller/examples/route-proxy 1.133s
ok github.com/novox/mesh-controller/internal/artifacts 1.074s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 4.022s
ok github.com/novox/mesh-controller/internal/builder 40.202s
ok github.com/novox/mesh-controller/internal/catalogue 7.641s
ok github.com/novox/mesh-controller/internal/conditions 2.573s
ok github.com/novox/mesh-controller/internal/envfile 1.031s
ok github.com/novox/mesh-controller/internal/facts 1.033s
ok github.com/novox/mesh-controller/internal/identity 4.453s
ok github.com/novox/mesh-controller/internal/inventory 94.997s
ok github.com/novox/mesh-controller/internal/lease 17.692s
ok github.com/novox/mesh-controller/internal/licences 4.056s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.037s
ok github.com/novox/mesh-controller/internal/link 61.044s
ok github.com/novox/mesh-controller/internal/lint 2.299s
ok github.com/novox/mesh-controller/internal/outward 1.048s
ok github.com/novox/mesh-controller/internal/overlay 1.083s
ok github.com/novox/mesh-controller/internal/secrets 1.411s
ok github.com/novox/mesh-controller/internal/store 3.347s
ok github.com/novox/mesh-controller/internal/testbus 1.207s
ok github.com/novox/mesh-controller/internal/token 1.019s
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (0.38s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (0.40s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (0.38s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (0.38s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (0.37s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (0.34s)
./cmd/mesh-controller --- PASS: TestAPlanFollowedFromTheStoreAnswersWhenItMoves (4.35s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (0.41s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.28s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (0.42s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (0.41s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (0.38s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (0.37s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (0.41s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.38s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (0.42s)
./cmd/mesh-controller --- PASS: TestReplay237 (0.35s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (0.36s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (0.36s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (0.36s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (0.40s)
./cmd/mesh-controller --- PASS: TestTheSendMakesNoValueForAnOutsideSecretNobodyGave (0.43s)
./cmd/mesh-controller --- PASS: TestAQuestionComposesWithoutAnOutsideSecretNobodyGave (0.45s)
./cmd/mesh-controller --- PASS: TestReplay201 (0.32s)
./cmd/mesh-controller --- PASS: TestARollbackWhoseSendWasRefusedIsCompletedByTheNextSend (0.32s)
./cmd/mesh-controller --- PASS: TestAGateJudgesTheOtherMovesBesideAKeptCore (0.33s)
./cmd/mesh-controller --- PASS: TestReplay401 (0.45s)
./cmd/mesh-controller --- PASS: TestReplay201ThePlansSend (0.39s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.22s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.22s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.24s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.23s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.22s)
./internal/inventory --- PASS: TestAPlanIdHoldingAQuoteIsReadAsAPlainId (0.21s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.22s)
Out of date when it landed: out of date: judged against trunk 2f157148c6, the trunk is now 961f2e82ea1c; judged again on a recheck or when it is merged
**Merge check** at `b5383970`
Judged: head `b5383970550b` merged into trunk `2f157148c6c8`; read beside it: mesh-catalog `9c9a76d220f8`, mesh-controller-main `2f157148c6c8`, mesh-host `8e95c1d9ed2d`, mesh-tools `954e1a53eef9`
- `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
**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
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent, route-proxy is judged on its first machine
Run by the build seat on ace as `build-1791839749749700026` (`builds --log build-1791839749749700026`).
```
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 58 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T21:08:25Z 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-12T21:08:25Z
modules the change moves:
- mesh-controller (changed)
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-delivery, 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 2 module(s) in 2 tier(s): build-agent, mesh-controller
notes:
- internal/catalogue/setting_takes_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.038s
ok github.com/novox/mesh-controller/cmd/mesh-controller 253.907s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.026s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.030s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.025s
ok github.com/novox/mesh-controller/examples/route-proxy 1.133s
ok github.com/novox/mesh-controller/internal/artifacts 1.074s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 4.022s
ok github.com/novox/mesh-controller/internal/builder 40.202s
ok github.com/novox/mesh-controller/internal/catalogue 7.641s
ok github.com/novox/mesh-controller/internal/conditions 2.573s
ok github.com/novox/mesh-controller/internal/envfile 1.031s
ok github.com/novox/mesh-controller/internal/facts 1.033s
ok github.com/novox/mesh-controller/internal/identity 4.453s
ok github.com/novox/mesh-controller/internal/inventory 94.997s
ok github.com/novox/mesh-controller/internal/lease 17.692s
ok github.com/novox/mesh-controller/internal/licences 4.056s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.037s
ok github.com/novox/mesh-controller/internal/link 61.044s
ok github.com/novox/mesh-controller/internal/lint 2.299s
ok github.com/novox/mesh-controller/internal/outward 1.048s
ok github.com/novox/mesh-controller/internal/overlay 1.083s
ok github.com/novox/mesh-controller/internal/secrets 1.411s
ok github.com/novox/mesh-controller/internal/store 3.347s
ok github.com/novox/mesh-controller/internal/testbus 1.207s
ok github.com/novox/mesh-controller/internal/token 1.019s
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (0.38s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (0.40s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (0.38s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (0.38s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (0.37s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (0.34s)
./cmd/mesh-controller --- PASS: TestAPlanFollowedFromTheStoreAnswersWhenItMoves (4.35s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (0.41s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.28s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (0.42s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (0.41s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (0.38s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (0.37s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (0.41s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.38s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (0.42s)
./cmd/mesh-controller --- PASS: TestReplay237 (0.35s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (0.36s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (0.36s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (0.36s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (0.40s)
./cmd/mesh-controller --- PASS: TestTheSendMakesNoValueForAnOutsideSecretNobodyGave (0.43s)
./cmd/mesh-controller --- PASS: TestAQuestionComposesWithoutAnOutsideSecretNobodyGave (0.45s)
./cmd/mesh-controller --- PASS: TestReplay201 (0.32s)
./cmd/mesh-controller --- PASS: TestARollbackWhoseSendWasRefusedIsCompletedByTheNextSend (0.32s)
./cmd/mesh-controller --- PASS: TestAGateJudgesTheOtherMovesBesideAKeptCore (0.33s)
./cmd/mesh-controller --- PASS: TestReplay401 (0.45s)
./cmd/mesh-controller --- PASS: TestReplay201ThePlansSend (0.39s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.22s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.22s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.24s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.23s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.22s)
./internal/inventory --- PASS: TestAPlanIdHoldingAQuoteIsReadAsAPlainId (0.21s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.22s)
```
**Out of date when it landed**: out of date: judged against trunk 2f157148c6c8, the trunk is now 961f2e82ea1c; judged again on a recheck or when it is merged
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
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent, route-proxy is judged on its first machine
Run by the build seat on ace as build-1791840291660042476 (builds --log build-1791840291660042476).
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 58 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T21:22:43Z 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-12T21:22:43Z
modules the change moves:
- mesh-controller (changed)
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-delivery, 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.037s
ok github.com/novox/mesh-controller/cmd/mesh-controller 267.224s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.025s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.033s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.023s
ok github.com/novox/mesh-controller/examples/route-proxy 1.197s
ok github.com/novox/mesh-controller/internal/artifacts 1.119s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 4.081s
ok github.com/novox/mesh-controller/internal/builder 49.094s
ok github.com/novox/mesh-controller/internal/catalogue 7.652s
ok github.com/novox/mesh-controller/internal/conditions 2.647s
ok github.com/novox/mesh-controller/internal/envfile 1.100s
ok github.com/novox/mesh-controller/internal/facts 1.102s
ok github.com/novox/mesh-controller/internal/identity 4.473s
ok github.com/novox/mesh-controller/internal/inventory 101.042s
ok github.com/novox/mesh-controller/internal/lease 17.741s
ok github.com/novox/mesh-controller/internal/licences 4.093s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.092s
ok github.com/novox/mesh-controller/internal/link 76.237s
ok github.com/novox/mesh-controller/internal/lint 2.303s
ok github.com/novox/mesh-controller/internal/outward 1.099s
ok github.com/novox/mesh-controller/internal/overlay 1.095s
ok github.com/novox/mesh-controller/internal/secrets 1.484s
ok github.com/novox/mesh-controller/internal/store 3.451s
ok github.com/novox/mesh-controller/internal/testbus 1.245s
ok github.com/novox/mesh-controller/internal/token 1.020s
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (0.39s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (0.40s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (0.38s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (0.38s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (0.37s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (0.34s)
./cmd/mesh-controller --- PASS: TestAPlanFollowedFromTheStoreAnswersWhenItMoves (4.36s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (0.41s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.30s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (0.45s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (0.42s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (0.37s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (0.39s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (0.44s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.39s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (0.44s)
./cmd/mesh-controller --- PASS: TestReplay237 (0.37s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (0.39s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (0.41s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (0.37s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (0.41s)
./cmd/mesh-controller --- PASS: TestTheSendMakesNoValueForAnOutsideSecretNobodyGave (0.46s)
./cmd/mesh-controller --- PASS: TestAQuestionComposesWithoutAnOutsideSecretNobodyGave (0.43s)
./cmd/mesh-controller --- PASS: TestReplay201 (0.34s)
./cmd/mesh-controller --- PASS: TestARollbackWhoseSendWasRefusedIsCompletedByTheNextSend (0.34s)
./cmd/mesh-controller --- PASS: TestAGateJudgesTheOtherMovesBesideAKeptCore (0.33s)
./cmd/mesh-controller --- PASS: TestReplay401 (0.45s)
./cmd/mesh-controller --- PASS: TestReplay201ThePlansSend (0.40s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.23s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.24s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.27s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.26s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.24s)
./internal/inventory --- PASS: TestAPlanIdHoldingAQuoteIsReadAsAPlainId (0.23s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.23s)
**Merge check** at `b5383970`
Judged: head `b5383970550b` merged into trunk `961f2e82ea1c`; read beside it: mesh-catalog `9c9a76d220f8`, mesh-controller-main `961f2e82ea1c`, mesh-host `8e95c1d9ed2d`, mesh-tools `954e1a53eef9`
- `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
**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
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent, route-proxy is judged on its first machine
Run by the build seat on ace as `build-1791840291660042476` (`builds --log build-1791840291660042476`).
```
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 58 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T21:22:43Z 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-12T21:22:43Z
modules the change moves:
- mesh-controller (changed)
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-delivery, 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.037s
ok github.com/novox/mesh-controller/cmd/mesh-controller 267.224s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.025s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.033s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.023s
ok github.com/novox/mesh-controller/examples/route-proxy 1.197s
ok github.com/novox/mesh-controller/internal/artifacts 1.119s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 4.081s
ok github.com/novox/mesh-controller/internal/builder 49.094s
ok github.com/novox/mesh-controller/internal/catalogue 7.652s
ok github.com/novox/mesh-controller/internal/conditions 2.647s
ok github.com/novox/mesh-controller/internal/envfile 1.100s
ok github.com/novox/mesh-controller/internal/facts 1.102s
ok github.com/novox/mesh-controller/internal/identity 4.473s
ok github.com/novox/mesh-controller/internal/inventory 101.042s
ok github.com/novox/mesh-controller/internal/lease 17.741s
ok github.com/novox/mesh-controller/internal/licences 4.093s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.092s
ok github.com/novox/mesh-controller/internal/link 76.237s
ok github.com/novox/mesh-controller/internal/lint 2.303s
ok github.com/novox/mesh-controller/internal/outward 1.099s
ok github.com/novox/mesh-controller/internal/overlay 1.095s
ok github.com/novox/mesh-controller/internal/secrets 1.484s
ok github.com/novox/mesh-controller/internal/store 3.451s
ok github.com/novox/mesh-controller/internal/testbus 1.245s
ok github.com/novox/mesh-controller/internal/token 1.020s
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (0.39s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (0.40s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (0.38s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (0.38s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (0.37s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (0.34s)
./cmd/mesh-controller --- PASS: TestAPlanFollowedFromTheStoreAnswersWhenItMoves (4.36s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (0.41s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.30s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (0.45s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (0.42s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (0.37s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (0.39s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (0.44s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.39s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (0.44s)
./cmd/mesh-controller --- PASS: TestReplay237 (0.37s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (0.39s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (0.41s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (0.37s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (0.41s)
./cmd/mesh-controller --- PASS: TestTheSendMakesNoValueForAnOutsideSecretNobodyGave (0.46s)
./cmd/mesh-controller --- PASS: TestAQuestionComposesWithoutAnOutsideSecretNobodyGave (0.43s)
./cmd/mesh-controller --- PASS: TestReplay201 (0.34s)
./cmd/mesh-controller --- PASS: TestARollbackWhoseSendWasRefusedIsCompletedByTheNextSend (0.34s)
./cmd/mesh-controller --- PASS: TestAGateJudgesTheOtherMovesBesideAKeptCore (0.33s)
./cmd/mesh-controller --- PASS: TestReplay401 (0.45s)
./cmd/mesh-controller --- PASS: TestReplay201ThePlansSend (0.40s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.23s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.24s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.27s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.26s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.24s)
./internal/inventory --- PASS: TestAPlanIdHoldingAQuoteIsReadAsAPlainId (0.23s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.23s)
```
Merge check at b5383970
Judged: head b5383970550b merged into trunk e63af0df17f5; read beside it: mesh-catalog 43a9155d5afe, mesh-controller-main e63af0df17f5, mesh-host 8e95c1d9ed2d, mesh-tools 954e1a53eef9
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)
mesh/repo-check: PASS — its merge-check.sh passed
Delivery plan — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
tier 0: mesh-controller
tier 1: build-agent
ace: receives build-agent
g14: receives build-agent
novox: receives mesh-controller, build-agent
shanks: receives build-agent
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent is judged on its first machine
read by no module's build: internal/catalogue/setting_takes_test.go
Run by the build seat on novox as build-1791841926054835969 (builds --log build-1791841926054835969).
--- the gate: build-agent, mesh-controller
mesh-controller: ok, 58 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T21:48:00Z 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-12T21:48:00Z
modules the change moves:
- mesh-controller (changed)
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-delivery, 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 2 module(s) in 2 tier(s): build-agent, mesh-controller
notes:
- internal/catalogue/setting_takes_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.049s
ok github.com/novox/mesh-controller/cmd/mesh-controller 324.708s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.020s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.027s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.018s
ok github.com/novox/mesh-controller/examples/route-proxy 1.149s
ok github.com/novox/mesh-controller/internal/artifacts 1.056s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 4.793s
ok github.com/novox/mesh-controller/internal/builder 46.577s
ok github.com/novox/mesh-controller/internal/catalogue 10.330s
ok github.com/novox/mesh-controller/internal/conditions 2.632s
ok github.com/novox/mesh-controller/internal/envfile 1.026s
ok github.com/novox/mesh-controller/internal/facts 1.028s
ok github.com/novox/mesh-controller/internal/identity 6.065s
ok github.com/novox/mesh-controller/internal/inventory 114.767s
ok github.com/novox/mesh-controller/internal/lease 17.629s
ok github.com/novox/mesh-controller/internal/licences 5.564s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.016s
ok github.com/novox/mesh-controller/internal/link 79.894s
ok github.com/novox/mesh-controller/internal/lint 2.513s
ok github.com/novox/mesh-controller/internal/outward 1.049s
ok github.com/novox/mesh-controller/internal/overlay 1.034s
ok github.com/novox/mesh-controller/internal/secrets 1.563s
ok github.com/novox/mesh-controller/internal/store 3.881s
ok github.com/novox/mesh-controller/internal/testbus 1.301s
ok github.com/novox/mesh-controller/internal/token 1.028s
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (0.48s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (0.51s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (0.47s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (0.49s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (0.48s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (0.42s)
./cmd/mesh-controller --- PASS: TestAPlanFollowedFromTheStoreAnswersWhenItMoves (4.43s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (0.51s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.66s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (0.52s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (0.52s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (0.45s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (0.46s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (0.50s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.45s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (0.52s)
./cmd/mesh-controller --- PASS: TestReplay237 (0.46s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (0.46s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (0.45s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (0.43s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (0.49s)
./cmd/mesh-controller --- PASS: TestTheSendMakesNoValueForAnOutsideSecretNobodyGave (0.61s)
./cmd/mesh-controller --- PASS: TestAQuestionComposesWithoutAnOutsideSecretNobodyGave (0.53s)
./cmd/mesh-controller --- PASS: TestReplay201 (0.39s)
./cmd/mesh-controller --- PASS: TestARollbackWhoseSendWasRefusedIsCompletedByTheNextSend (0.40s)
./cmd/mesh-controller --- PASS: TestAGateJudgesTheOtherMovesBesideAKeptCore (0.42s)
./cmd/mesh-controller --- PASS: TestReplay401 (0.63s)
./cmd/mesh-controller --- PASS: TestReplay201ThePlansSend (0.50s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.32s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.32s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.32s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.36s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.30s)
./internal/inventory --- PASS: TestAPlanIdHoldingAQuoteIsReadAsAPlainId (0.32s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.28s)
./internal/inventory --- PASS: TestAWalksRestIsReadFromEachMachinesOwnSend (0.30s)
**Merge check** at `b5383970`
Judged: head `b5383970550b` merged into trunk `e63af0df17f5`; read beside it: mesh-catalog `43a9155d5afe`, mesh-controller-main `e63af0df17f5`, mesh-host `8e95c1d9ed2d`, mesh-tools `954e1a53eef9`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Delivery plan** — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- ace: receives build-agent
- g14: receives build-agent
- novox: receives mesh-controller, build-agent
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before build-agent is judged on its first machine
- read by no module's build: internal/catalogue/setting_takes_test.go
Run by the build seat on novox as `build-1791841926054835969` (`builds --log build-1791841926054835969`).
```
--- the gate: build-agent, mesh-controller
mesh-controller: ok, 58 tool(s); WARNING: merge-window ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 1
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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T21:48:00Z 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-12T21:48:00Z
modules the change moves:
- mesh-controller (changed)
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-delivery, 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 2 module(s) in 2 tier(s): build-agent, mesh-controller
notes:
- internal/catalogue/setting_takes_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.049s
ok github.com/novox/mesh-controller/cmd/mesh-controller 324.708s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.020s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.027s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.018s
ok github.com/novox/mesh-controller/examples/route-proxy 1.149s
ok github.com/novox/mesh-controller/internal/artifacts 1.056s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 4.793s
ok github.com/novox/mesh-controller/internal/builder 46.577s
ok github.com/novox/mesh-controller/internal/catalogue 10.330s
ok github.com/novox/mesh-controller/internal/conditions 2.632s
ok github.com/novox/mesh-controller/internal/envfile 1.026s
ok github.com/novox/mesh-controller/internal/facts 1.028s
ok github.com/novox/mesh-controller/internal/identity 6.065s
ok github.com/novox/mesh-controller/internal/inventory 114.767s
ok github.com/novox/mesh-controller/internal/lease 17.629s
ok github.com/novox/mesh-controller/internal/licences 5.564s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.016s
ok github.com/novox/mesh-controller/internal/link 79.894s
ok github.com/novox/mesh-controller/internal/lint 2.513s
ok github.com/novox/mesh-controller/internal/outward 1.049s
ok github.com/novox/mesh-controller/internal/overlay 1.034s
ok github.com/novox/mesh-controller/internal/secrets 1.563s
ok github.com/novox/mesh-controller/internal/store 3.881s
ok github.com/novox/mesh-controller/internal/testbus 1.301s
ok github.com/novox/mesh-controller/internal/token 1.028s
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (0.48s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (0.51s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (0.47s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (0.49s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (0.48s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (0.42s)
./cmd/mesh-controller --- PASS: TestAPlanFollowedFromTheStoreAnswersWhenItMoves (4.43s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (0.51s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.66s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (0.52s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (0.52s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (0.45s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (0.46s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (0.50s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.45s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (0.52s)
./cmd/mesh-controller --- PASS: TestReplay237 (0.46s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (0.46s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (0.45s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (0.43s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (0.49s)
./cmd/mesh-controller --- PASS: TestTheSendMakesNoValueForAnOutsideSecretNobodyGave (0.61s)
./cmd/mesh-controller --- PASS: TestAQuestionComposesWithoutAnOutsideSecretNobodyGave (0.53s)
./cmd/mesh-controller --- PASS: TestReplay201 (0.39s)
./cmd/mesh-controller --- PASS: TestARollbackWhoseSendWasRefusedIsCompletedByTheNextSend (0.40s)
./cmd/mesh-controller --- PASS: TestAGateJudgesTheOtherMovesBesideAKeptCore (0.42s)
./cmd/mesh-controller --- PASS: TestReplay401 (0.63s)
./cmd/mesh-controller --- PASS: TestReplay201ThePlansSend (0.50s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.32s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.32s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.32s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.36s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.30s)
./internal/inventory --- PASS: TestAPlanIdHoldingAQuoteIsReadAsAPlainId (0.32s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.28s)
./internal/inventory --- PASS: TestAWalksRestIsReadFromEachMachinesOwnSend (0.30s)
```
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.
What
A resource that says
mergemay carrytakes-settings, a list of top-level setting keys (hq ADR 0326):ApplySettingslays only the named keys over that file; an empty list takes none. The field is removed withmergeandprotected, so it never reaches the node-engine. On a file that does not merge it is refused rather than passed on.UnusedSettings: for a module whose mergeable files all name their keys, a key lands in a mergeable file only when a file names it. Anything else not taken elsewhere is stray, and the message says which keys each file takes. A module none of whose files name keys keeps today's form, with nothing stray.TakenSettingsProblems, run by the module check (ParseManifest) and byJudgeSettings, refuses: the field on a non-merging file, a value that is not a list, a key named twice, a mesh word, a protected key, and a module with one naming and one silent mergeable file.286257d).declaration.gois untouched (PR #262 changes it).Why
hq issue 168. Every key of a module's layers merged into every mergeable file it owns: searxng's
endpointslanded in itssettings.yml, keycloak'sissuerin its tools'config.json. So a module could not own two configurable files. ADR 0164 §11 decided that a setting names the files that read it. ADR 0326 spells that from the file's side, so the operator's own values stay declared nowhere (ADR 0262 §2).How it was tested
internal/catalogue/setting_takes_test.gocovers a module with two mergeable files where each takes only its named keys, an empty list, today's form kept, a stray key, mixed naming refused, and every refusal of §4. Every settled file is also checked for the field's removal.TestEachMergeableFileTakesOnlyTheKeysItNames,TestAnEmptyListTakesNoSettingandTestAKeyNoFileNamesIsStrayfail.sh merge-check.shpasses locally. Store tests were skipped because there was noMESH_TEST_POSTGRES.internal/catalogue,cmd/mesh-controller) were run withMESH_CHECK_BESIDEat catalogue main (cd2b6aa) and at mesh-catalog #252's head. Both pass, exceptTestTheResolvedPathRulesAreTheNodeEnginesOwn, which needs mesh-host beside and was not set up locally.Order
This controller must finish its walk before mesh-catalog #252 (which adds
takes-settings) merges. An older controller passes the field to the node-engine, which parses resources strictly.Fixes issue 168.
Every key of a module's layers merged into every mergeable file it owns: the mesh's own words, a key meant for a ${setting:} in another file, a key for a second configuration file. A module could not own two configurable files. A file now names its keys in takes-settings and takes only those; a key no file names is stray where it is set; a module that declares a setting names the keys of every mergeable file, and one that declares none keeps today's form (ADR 0164 §15).Delivery
novox/mesh-controller@b5383970550b— delivered since 2026-10-12T22:14:58ZDelivery plan — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
Machines
Transitions
961f2e82ea, the trunk is now e63af0df17f5; judged again on a recheck or when it is mergedThe commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Merge check at
286257d8mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)mesh/repo-check: FAIL — its merge-check.sh failed: --- FAIL: TestModuleCheckPassesTheCatalogue (0.89s); and TestEveryCatalogueManifestParses, TestNoCatalogueManifestNamesAnInstallation, TestEveryCatalogueIdentityFitsWhatItRequires, TestEveryCatalogueManifestDeclaresWhatItMountsDelivery plan — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
Run by the build seat on ace as
build-1791820047075813566(builds --log build-1791820047075813566).Merge check at
b5383970mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
Run by the build seat on shanks as
build-1791820872948188758(builds --log build-1791820872948188758).Merge check at
dd108892mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
Run by the build seat on g14 as
build-1791820842516900020(builds --log build-1791820842516900020).Verdict: approve at
b538397055Independent review for hq issue 168 against ADR 0326 (read whole with knowledge-base.get 326), ADR 0164 and ADR 0262.
prefs. The catalogue cannot name betterbird's keys before a controller that strips the field runs, because #252's gate shows the node-engine refuses it. Without the refusal, betterbird composes exactly as today, so nothing live changes. The only gap is a new declaring module with a silent mergeable file registering between this merge and issue 574; the window is small, and 574 keeps the code and the test from286257d. Its clause-7 test goes with it, so clause 7 is complete only once 574 lands.No live change
I fetched the facts snapshot of 16:04Z and composed every machine (4 of 4) with controller main and with this head in throwaway stores. I did it twice: once with the stored definitions, and once with every definition of mesh-catalog main 23ea0f4 and mesh-media-catalog main 94b80fb laid over them (49 modules moved). In both runs the two declarations are byte-identical once fresh secret material is normalised. Every raw difference was a sealed value, a minted secret, a bcrypt hash or a WireGuard key that each throwaway store mints anew. No problems, nothing left out, and no definition on either main carries takes-settings.
Stripping
I composed the same snapshot with #252 merged into catalogue main. Controller main sends takes-settings and refuses exactly 3 resources: betterbird.accounts, keycloak.runtime-config and searxng.settings, with the node-engine's error "a file does not use takes-settings". This head composes all 4 machines with no problem, and the field appears 0 times.
Tests
I put main's settings.go and manifest.go under the new tests, and 5 of the 7 tests fail. TestAFileThatNamesNothingKeepsTodaysForm is the regression guard and passes either way, as it should. TestASoftwareSpelledKeyIsUsable tests the new file alone, so it also passes. I removed only the delete line: the strip assertion fails. I removed only the onlyTaken call: the filter tests fail. merge-check.sh with a throwaway PostgreSQL 18 exits 0: gofmt, go vet, go test -race, and the store tests ran with nothing skipped.
Statuses at this head
mesh/merge-gate success (4 of 4 machines compose as they did), mesh/repo-check success, mesh/delivery ready.
Order: merge this, wait until mesh-controller.plans says done, then mesh-catalog #252, then issue 574.
Merge check at
b5383970Judged: head
b5383970550bmerged into trunk2f157148c6c8; read beside it: mesh-catalog9c9a76d220f8, mesh-controller-main2f157148c6c8, mesh-hostd8e785bb4b4b, mesh-tools954e1a53eef9mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)mesh/repo-check: FAIL — its merge-check.sh failed: --- FAIL: TestTheSecondControllerWaitsAndTakesAHigherEpochOnHandover (4.06s)Delivery plan — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
Run by the build seat on g14 as
build-1791838332100947375(builds --log build-1791838332100947375).Merge check at
b5383970Judged: head
b5383970550bmerged into trunk2f157148c6c8; read beside it: mesh-catalog9c9a76d220f8, mesh-controller-main2f157148c6c8, mesh-host8e95c1d9ed2d, mesh-tools954e1a53eef9mesh/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 passedDelivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Run by the build seat on ace as
build-1791839749749700026(builds --log build-1791839749749700026).Out of date when it landed: out of date: judged against trunk
2f157148c6, the trunk is now 961f2e82ea1c; judged again on a recheck or when it is mergedMerge check at
b5383970Judged: head
b5383970550bmerged into trunk961f2e82ea1c; read beside it: mesh-catalog9c9a76d220f8, mesh-controller-main961f2e82ea1c, mesh-host8e95c1d9ed2d, mesh-tools954e1a53eef9mesh/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 passedDelivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Run by the build seat on ace as
build-1791840291660042476(builds --log build-1791840291660042476).Merge check at
b5383970Judged: head
b5383970550bmerged into trunke63af0df17f5; read beside it: mesh-catalog43a9155d5afe, mesh-controller-maine63af0df17f5, mesh-host8e95c1d9ed2d, mesh-tools954e1a53eef9mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step
Run by the build seat on novox as
build-1791841926054835969(builds --log build-1791841926054835969).