Issue 594 (a send that recreates a build agent kills the check it runs); decision: novox/hq ADR 0335. In a delivery group with mesh-controller#283, which goes after it.
What it does
Declaration: a container may carry busy: {command, timeout} (timeout default 10s, at most 1m), read strictly, refused on a step or a scheduled run. Not part of the container's spec: a changed busy command never recreates it.
Apply: when an apply would replace a running container that declares busy, it runs the command inside it (docker exec <name> /bin/sh -c <command>, as an exec health check). Exit 0: the container is left running (action waits-busy, not a change), everything else of the declaration applies, and the wait is kept in its record (busy_since in the state on disk), so the bound runs from the first apply that would have replaced it across passes and across a restart. Non-zero, or no answer within the timeout: replaced. Still busy 15 minutes after the first such apply: replaced anyway.
Report: busy lists each container waiting, replaced-when-idle or replaced-at-bound, with since, until and the command's last output. A wait starting or ending is news for the reconcile.
Passes: while something waits, a reconcile is asked every 20 s (it only enqueues; the queue's worker applies). The machine's lock is held for one ask, never for the wait.
Health statement contract 8 (BusyContract): what tells the controller this engine may be sent busy.
Since the review (b9a293f): a replacement owed since a busy wait stays owed (a restart-on trigger that is no file counted as changed only in its own pass, so the container read unchanged afterwards and dropped from the report as if replaced), and it stays owed through a maintenance window; a busy_since from a clock that went back is clamped to now. Merged with origin/main (one conflict in the report fingerprint, beside ADR 0340's networks); contract 8 is still free on main.
Tests (fail on main: the field is refused there)
internal/apply busy_test.go: left running while busy and the rest applied, replaced on the first idle pass; idle replaced at once, never asked when nothing moved; replaced at 15 minutes with the last output, across a save/load of the state; another module's send applies at once; the owed replacement after a non-file restart-on trigger (fails without the fix); a wait from a later clock clamped; an ask that fails (no shell, a timeout) is idle; a stopped container is replaced unasked; busy's shape.
cmd/mesh-host busy_test.go: a wait is news when it starts and ends, not on its output; passes every 20 s only while something waits. units_test: contract 8.
gofmt, go vet and go test -race ./... (merge-check.sh, without a bus) pass.
after: none
Issue 594 (a send that recreates a build agent kills the check it runs); decision: novox/hq ADR 0335. In a delivery group with mesh-controller#283, which goes after it.
**What it does**
- Declaration: a container may carry `busy: {command, timeout}` (timeout default 10s, at most 1m), read strictly, refused on a step or a scheduled run. Not part of the container's spec: a changed busy command never recreates it.
- Apply: when an apply would replace a running container that declares busy, it runs the command inside it (`docker exec <name> /bin/sh -c <command>`, as an exec health check). Exit 0: the container is left running (action `waits-busy`, not a change), everything else of the declaration applies, and the wait is kept in its record (`busy_since` in the state on disk), so the bound runs from the first apply that would have replaced it across passes and across a restart. Non-zero, or no answer within the timeout: replaced. Still busy 15 minutes after the first such apply: replaced anyway.
- Report: `busy` lists each container `waiting`, `replaced-when-idle` or `replaced-at-bound`, with since, until and the command's last output. A wait starting or ending is news for the reconcile.
- Passes: while something waits, a reconcile is asked every 20 s (it only enqueues; the queue's worker applies). The machine's lock is held for one ask, never for the wait.
- Health statement contract 8 (`BusyContract`): what tells the controller this engine may be sent `busy`.
**Since the review (b9a293f):** a replacement owed since a busy wait stays owed (a restart-on trigger that is no file counted as changed only in its own pass, so the container read unchanged afterwards and dropped from the report as if replaced), and it stays owed through a maintenance window; a busy_since from a clock that went back is clamped to now. Merged with origin/main (one conflict in the report fingerprint, beside ADR 0340's networks); contract 8 is still free on main.
**Tests (fail on main: the field is refused there)**
- internal/apply busy_test.go: left running while busy and the rest applied, replaced on the first idle pass; idle replaced at once, never asked when nothing moved; replaced at 15 minutes with the last output, across a save/load of the state; another module's send applies at once; the owed replacement after a non-file restart-on trigger (fails without the fix); a wait from a later clock clamped; an ask that fails (no shell, a timeout) is idle; a stopped container is replaced unasked; busy's shape.
- cmd/mesh-host busy_test.go: a wait is news when it starts and ends, not on its output; passes every 20 s only while something waits. units_test: contract 8.
gofmt, go vet and `go test -race ./...` (merge-check.sh, without a bus) pass.
mesh/delivery-group group feat/335-a-busy-container-is-replaced-when-idle rejected: its order contradicts itself: novox/mesh-catalog@190608193764, novox/mesh-c…
A send that replaced the build agent killed the check it ran, and the queue
started it again elsewhere (issue 594). A container may now declare busy; the
node-engine asks it before replacing it, applies everything else, says the
wait, and replaces it on the first idle pass or at the bound, kept across
restarts (novox/hq ADR 0335).
Deliverynovox/mesh-host@b9a293f8c8bc — delivered since 2026-10-13T22:34:23Z
Delivery plan — builds mesh-host → ace, g14, novox, shanks; no bus step
tier 0: mesh-host
ace: receives mesh-host
g14: receives mesh-host
novox: receives mesh-host
shanks: receives mesh-host
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 mesh-host is judged on its first machine
composed together: pass — every machine composes with the change as it did without (4 of 4 compose)
Machines
mesh-host on ace: passed — judged with build-agent: healthy 3 times over 2m12s, by the core's rule: 3 readings, or healthy throughout 2m0s after the send (novox/hq ADR 0352)
build-agent on ace: passed — healthy 3 times over 2m12s, by the core's rule: 3 readings, or healthy throughout 2m0s after the send (novox/hq ADR 0352)
route-proxy on ace: passed — judged with build-agent: healthy 3 times over 2m12s, by the core's rule: 3 readings, or healthy throughout 2m0s after the send (novox/hq ADR 0352)
mesh-host on g14: passed — carried by release-1791930194184991192
mesh-host on shanks: passed — carried by release-1791930194184991192
mesh-host on novox: passed — carried by release-1791930194184991192
mesh-controller on novox: passed — healthy 1 times over 1m32s, by the controller's rule: one reading once it is ready, after the node-engine's witness window (novox/hq ADR 0351)
build-agent on the rest running it: sent
mesh-host on the rest running it: sent
route-proxy on the rest running it: sent
mesh-controller on the rest running it: sent
Transitions
2026-10-13 22:00 (new) → proposed (announced): novox/mesh-host#98's head announced
2026-10-13 22:03 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
2026-10-13 22:03 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-13 22:23 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-13 22:23 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-13 22:34 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-host@b9a293f8c8bc` — **delivered** since 2026-10-13T22:34:23Z
**Delivery plan** — builds mesh-host → ace, g14, novox, shanks; no bus step
- tier 0: mesh-host
- ace: receives mesh-host
- g14: receives mesh-host
- novox: receives mesh-host
- shanks: receives mesh-host
- 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 mesh-host is judged on its first machine
**Group** `feat/335-a-busy-container-is-replaced-when-idle`, in order: novox/mesh-host@b9a293f8c8bc → novox/mesh-controller@873b19566a82
- novox/mesh-host@b9a293f8c8bc before novox/mesh-controller@873b19566a82: declared, over built by
- composed together: pass — every machine composes with the change as it did without (4 of 4 compose)
**Machines**
- mesh-host on ace: passed — judged with build-agent: healthy 3 times over 2m12s, by the core's rule: 3 readings, or healthy throughout 2m0s after the send (novox/hq ADR 0352)
- build-agent on ace: passed — healthy 3 times over 2m12s, by the core's rule: 3 readings, or healthy throughout 2m0s after the send (novox/hq ADR 0352)
- route-proxy on ace: passed — judged with build-agent: healthy 3 times over 2m12s, by the core's rule: 3 readings, or healthy throughout 2m0s after the send (novox/hq ADR 0352)
- mesh-host on g14: passed — carried by release-1791930194184991192
- mesh-host on shanks: passed — carried by release-1791930194184991192
- mesh-host on novox: passed — carried by release-1791930194184991192
- mesh-controller on novox: passed — healthy 1 times over 1m32s, by the controller's rule: one reading once it is ready, after the node-engine's witness window (novox/hq ADR 0351)
- build-agent on the rest running it: sent
- mesh-host on the rest running it: sent
- route-proxy on the rest running it: sent
- mesh-controller on the rest running it: sent
**Transitions**
- 2026-10-13 22:00 (new) → proposed (announced): novox/mesh-host#98's head announced
- 2026-10-13 22:03 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
- 2026-10-13 22:03 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-13 22:23 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-13 22:23 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-13 22:34 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`.
Merge check at bb60e7b5
Judged: head bb60e7b584d8 merged into trunk 7a41e120635b; read beside it: mesh-catalog 8f80cd471634, mesh-controller 56d6313262e8, mesh-controller-main 56d6313262e8, mesh-tools 954e1a53eef9
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-host)
mesh/repo-check: PASS — its merge-check.sh passed
Delivery plan — builds mesh-host → ace, g14, novox, shanks; no bus step
tier 0: mesh-host
ace: receives mesh-host
g14: receives mesh-host
novox: receives mesh-host
shanks: receives mesh-host
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 mesh-host is judged on its first machine
read by no module's build: cmd/mesh-host/busy_test.go, cmd/mesh-host/units_test.go, internal/apply/busy_test.go
Run by the build seat on novox as build-1791845685162105257 (builds --log build-1791845685162105257).
--- the gate: mesh-host
mesh-host: ok
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 0
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T22:43:48Z 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-12T22:43:48Z
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 1 module(s) in 1 tier(s): mesh-host
notes:
- cmd/mesh-host/busy_test.go, cmd/mesh-host/units_test.go and internal/apply/busy_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-host/cmd/mesh-bootstrap 1.013s
ok github.com/novox/mesh-host/cmd/mesh-host 8.864s
ok github.com/novox/mesh-host/examples 1.024s
ok github.com/novox/mesh-host/internal/accounts 2.337s
ok github.com/novox/mesh-host/internal/apply 41.641s
ok github.com/novox/mesh-host/internal/bootstrap 5.646s
ok github.com/novox/mesh-host/internal/bundle 1.028s
ok github.com/novox/mesh-host/internal/declaration 1.070s
ok github.com/novox/mesh-host/internal/firewall 1.851s
ok github.com/novox/mesh-host/internal/identity 1.587s
ok github.com/novox/mesh-host/internal/image 1.023s
ok github.com/novox/mesh-host/internal/inventory 1.033s
ok github.com/novox/mesh-host/internal/link 10.557s
ok github.com/novox/mesh-host/internal/liveness 2.873s
ok github.com/novox/mesh-host/internal/meshcli 1.552s
ok github.com/novox/mesh-host/internal/network 1.042s
ok github.com/novox/mesh-host/internal/outward 1.015s
ok github.com/novox/mesh-host/internal/profile 1.587s
ok github.com/novox/mesh-host/internal/reachable 1.012s
ok github.com/novox/mesh-host/internal/store 2.456s
ok github.com/novox/mesh-host/internal/system 1.021s
ok github.com/novox/mesh-host/internal/tunnel 1.015s
ok github.com/novox/mesh-host/internal/units 1.007s
ok github.com/novox/mesh-host/internal/upgrade 2.128s
ok github.com/novox/mesh-host/internal/witness 44.067s
ok github.com/novox/mesh-host/packaging 1.009s
? github.com/novox/mesh-host/rootsearch [no test files]
ok github.com/novox/mesh-host/validate 1.009s
**Merge check** at `bb60e7b5`
Judged: head `bb60e7b584d8` merged into trunk `7a41e120635b`; read beside it: mesh-catalog `8f80cd471634`, mesh-controller `56d6313262e8`, mesh-controller-main `56d6313262e8`, mesh-tools `954e1a53eef9`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-host)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Delivery plan** — builds mesh-host → ace, g14, novox, shanks; no bus step
- tier 0: mesh-host
- ace: receives mesh-host
- g14: receives mesh-host
- novox: receives mesh-host
- shanks: receives mesh-host
- 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 mesh-host is judged on its first machine
- read by no module's build: cmd/mesh-host/busy_test.go, cmd/mesh-host/units_test.go, internal/apply/busy_test.go
Run by the build seat on novox as `build-1791845685162105257` (`builds --log build-1791845685162105257`).
```
--- the gate: mesh-host
mesh-host: ok
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 0
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T22:43:48Z 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-12T22:43:48Z
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 1 module(s) in 1 tier(s): mesh-host
notes:
- cmd/mesh-host/busy_test.go, cmd/mesh-host/units_test.go and internal/apply/busy_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-host/cmd/mesh-bootstrap 1.013s
ok github.com/novox/mesh-host/cmd/mesh-host 8.864s
ok github.com/novox/mesh-host/examples 1.024s
ok github.com/novox/mesh-host/internal/accounts 2.337s
ok github.com/novox/mesh-host/internal/apply 41.641s
ok github.com/novox/mesh-host/internal/bootstrap 5.646s
ok github.com/novox/mesh-host/internal/bundle 1.028s
ok github.com/novox/mesh-host/internal/declaration 1.070s
ok github.com/novox/mesh-host/internal/firewall 1.851s
ok github.com/novox/mesh-host/internal/identity 1.587s
ok github.com/novox/mesh-host/internal/image 1.023s
ok github.com/novox/mesh-host/internal/inventory 1.033s
ok github.com/novox/mesh-host/internal/link 10.557s
ok github.com/novox/mesh-host/internal/liveness 2.873s
ok github.com/novox/mesh-host/internal/meshcli 1.552s
ok github.com/novox/mesh-host/internal/network 1.042s
ok github.com/novox/mesh-host/internal/outward 1.015s
ok github.com/novox/mesh-host/internal/profile 1.587s
ok github.com/novox/mesh-host/internal/reachable 1.012s
ok github.com/novox/mesh-host/internal/store 2.456s
ok github.com/novox/mesh-host/internal/system 1.021s
ok github.com/novox/mesh-host/internal/tunnel 1.015s
ok github.com/novox/mesh-host/internal/units 1.007s
ok github.com/novox/mesh-host/internal/upgrade 2.128s
ok github.com/novox/mesh-host/internal/witness 44.067s
ok github.com/novox/mesh-host/packaging 1.009s
? github.com/novox/mesh-host/rootsearch [no test files]
ok github.com/novox/mesh-host/validate 1.009s
```
A restart-on trigger that is no file counts as changed only in its own pass,
so after a busy wait the container read unchanged and was never replaced,
while the report stopped listing it (review of #98).
mesh/merge-gate head b9a293f8c8bc merged into trunk 0e92ef3d1b21 — pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes wi…
Merge check at b9a293f8
Judged: head b9a293f8c8bc merged into trunk 0e92ef3d1b21; read beside it: mesh-catalog 23a2e1e20467, mesh-controller 72214ae989b3, mesh-controller-main 72214ae989b3, mesh-tools 954e1a53eef9
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-host)
mesh/repo-check: PASS — its merge-check.sh passed
Delivery plan — builds mesh-host → ace, g14, novox, shanks; no bus step
tier 0: mesh-host
ace: receives mesh-host
g14: receives mesh-host
novox: receives mesh-host
shanks: receives mesh-host
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 mesh-host is judged on its first machine
read by no module's build: cmd/mesh-host/busy_test.go, cmd/mesh-host/units_test.go, internal/apply/busy_test.go
Run by the build seat on ace as build-1791928851227832079 (builds --log build-1791928851227832079).
--- the gate: mesh-host
mesh-host: ok
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 0
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-13T21:43:06Z 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-13T21:43:06Z
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 1 module(s) in 1 tier(s): mesh-host
notes:
- cmd/mesh-host/busy_test.go, cmd/mesh-host/units_test.go and internal/apply/busy_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-host/cmd/mesh-bootstrap 1.014s
ok github.com/novox/mesh-host/cmd/mesh-host 5.827s
ok github.com/novox/mesh-host/examples 1.026s
ok github.com/novox/mesh-host/internal/accounts 1.441s
ok github.com/novox/mesh-host/internal/apply 5.026s
ok github.com/novox/mesh-host/internal/bootstrap 3.975s
ok github.com/novox/mesh-host/internal/bundle 1.035s
ok github.com/novox/mesh-host/internal/declaration 1.079s
ok github.com/novox/mesh-host/internal/firewall 1.678s
ok github.com/novox/mesh-host/internal/identity 1.113s
ok github.com/novox/mesh-host/internal/image 1.034s
ok github.com/novox/mesh-host/internal/inventory 1.067s
ok github.com/novox/mesh-host/internal/link 10.514s
ok github.com/novox/mesh-host/internal/liveness 2.130s
ok github.com/novox/mesh-host/internal/meshcli 1.561s
ok github.com/novox/mesh-host/internal/network 1.049s
ok github.com/novox/mesh-host/internal/outward 1.041s
ok github.com/novox/mesh-host/internal/profile 1.637s
ok github.com/novox/mesh-host/internal/reachable 1.039s
ok github.com/novox/mesh-host/internal/store 1.263s
ok github.com/novox/mesh-host/internal/system 1.079s
ok github.com/novox/mesh-host/internal/tunnel 1.081s
ok github.com/novox/mesh-host/internal/units 1.073s
ok github.com/novox/mesh-host/internal/upgrade 1.202s
ok github.com/novox/mesh-host/internal/witness 4.754s
ok github.com/novox/mesh-host/packaging 1.075s
? github.com/novox/mesh-host/rootsearch [no test files]
ok github.com/novox/mesh-host/validate 1.074s
**Merge check** at `b9a293f8`
Judged: head `b9a293f8c8bc` merged into trunk `0e92ef3d1b21`; read beside it: mesh-catalog `23a2e1e20467`, mesh-controller `72214ae989b3`, mesh-controller-main `72214ae989b3`, mesh-tools `954e1a53eef9`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-host)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Delivery plan** — builds mesh-host → ace, g14, novox, shanks; no bus step
- tier 0: mesh-host
- ace: receives mesh-host
- g14: receives mesh-host
- novox: receives mesh-host
- shanks: receives mesh-host
- 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 mesh-host is judged on its first machine
- read by no module's build: cmd/mesh-host/busy_test.go, cmd/mesh-host/units_test.go, internal/apply/busy_test.go
Run by the build seat on ace as `build-1791928851227832079` (`builds --log build-1791928851227832079`).
```
--- the gate: mesh-host
mesh-host: ok
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 0
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-13T21:43:06Z 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-13T21:43:06Z
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 1 module(s) in 1 tier(s): mesh-host
notes:
- cmd/mesh-host/busy_test.go, cmd/mesh-host/units_test.go and internal/apply/busy_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-host/cmd/mesh-bootstrap 1.014s
ok github.com/novox/mesh-host/cmd/mesh-host 5.827s
ok github.com/novox/mesh-host/examples 1.026s
ok github.com/novox/mesh-host/internal/accounts 1.441s
ok github.com/novox/mesh-host/internal/apply 5.026s
ok github.com/novox/mesh-host/internal/bootstrap 3.975s
ok github.com/novox/mesh-host/internal/bundle 1.035s
ok github.com/novox/mesh-host/internal/declaration 1.079s
ok github.com/novox/mesh-host/internal/firewall 1.678s
ok github.com/novox/mesh-host/internal/identity 1.113s
ok github.com/novox/mesh-host/internal/image 1.034s
ok github.com/novox/mesh-host/internal/inventory 1.067s
ok github.com/novox/mesh-host/internal/link 10.514s
ok github.com/novox/mesh-host/internal/liveness 2.130s
ok github.com/novox/mesh-host/internal/meshcli 1.561s
ok github.com/novox/mesh-host/internal/network 1.049s
ok github.com/novox/mesh-host/internal/outward 1.041s
ok github.com/novox/mesh-host/internal/profile 1.637s
ok github.com/novox/mesh-host/internal/reachable 1.039s
ok github.com/novox/mesh-host/internal/store 1.263s
ok github.com/novox/mesh-host/internal/system 1.079s
ok github.com/novox/mesh-host/internal/tunnel 1.081s
ok github.com/novox/mesh-host/internal/units 1.073s
ok github.com/novox/mesh-host/internal/upgrade 1.202s
ok github.com/novox/mesh-host/internal/witness 4.754s
ok github.com/novox/mesh-host/packaging 1.075s
? github.com/novox/mesh-host/rootsearch [no test files]
ok github.com/novox/mesh-host/validate 1.074s
```
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.
after: none
Issue 594 (a send that recreates a build agent kills the check it runs); decision: novox/hq ADR 0335. In a delivery group with mesh-controller#283, which goes after it.
What it does
busy: {command, timeout}(timeout default 10s, at most 1m), read strictly, refused on a step or a scheduled run. Not part of the container's spec: a changed busy command never recreates it.docker exec <name> /bin/sh -c <command>, as an exec health check). Exit 0: the container is left running (actionwaits-busy, not a change), everything else of the declaration applies, and the wait is kept in its record (busy_sincein the state on disk), so the bound runs from the first apply that would have replaced it across passes and across a restart. Non-zero, or no answer within the timeout: replaced. Still busy 15 minutes after the first such apply: replaced anyway.busylists each containerwaiting,replaced-when-idleorreplaced-at-bound, with since, until and the command's last output. A wait starting or ending is news for the reconcile.BusyContract): what tells the controller this engine may be sentbusy.Since the review (
b9a293f): a replacement owed since a busy wait stays owed (a restart-on trigger that is no file counted as changed only in its own pass, so the container read unchanged afterwards and dropped from the report as if replaced), and it stays owed through a maintenance window; a busy_since from a clock that went back is clamped to now. Merged with origin/main (one conflict in the report fingerprint, beside ADR 0340's networks); contract 8 is still free on main.Tests (fail on main: the field is refused there)
gofmt, go vet and
go test -race ./...(merge-check.sh, without a bus) pass.Delivery
novox/mesh-host@b9a293f8c8bc— delivered since 2026-10-13T22:34:23ZDelivery plan — builds mesh-host → ace, g14, novox, shanks; no bus step
Group
feat/335-a-busy-container-is-replaced-when-idle, in order: novox/mesh-host@b9a293f8c8 → novox/mesh-controller@873b19566aMachines
Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Merge check at
bb60e7b5Judged: head
bb60e7b584d8merged into trunk7a41e120635b; read beside it: mesh-catalog8f80cd471634, mesh-controller56d6313262e8, mesh-controller-main56d6313262e8, mesh-tools954e1a53eef9mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-host)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds mesh-host → ace, g14, novox, shanks; no bus step
Run by the build seat on novox as
build-1791845685162105257(builds --log build-1791845685162105257).Merge check at
b9a293f8Judged: head
b9a293f8c8bcmerged into trunk0e92ef3d1b21; read beside it: mesh-catalog23a2e1e20467, mesh-controller72214ae989b3, mesh-controller-main72214ae989b3, mesh-tools954e1a53eef9mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-host)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds mesh-host → ace, g14, novox, shanks; no bus step
Run by the build seat on ace as
build-1791928851227832079(builds --log build-1791928851227832079).