Issue: hq issue 745 (a session cannot hear the bus). Decision: novox/hq ADR 0367 (a session waits on the bus for an event instead of polling), version 13.
What it does:
A new manifest word, waits: the event families a session may wait on through the mesh MCP server's mesh_wait. Only node-tools may declare it, one family at a time, never with a wildcard. Anything else is refused at parse.
The inventory resolves each family the way consumes is resolved. A seat's event goes under the seat and a module's under the module. A family on a seat whose events end in a kind or an asker (such as operator-channel.decided.claude-code) must name that last token, and is refused at composition without it.
The tool runner's account is granted a plain subscription on those subjects alone. No durable consumer is made for them, and nothing else widens the grant.
The tool runner's membership names the same list (waits), which mesh_wait reads to refuse any other family.
Tests: the composition test from ADR 0367's "How it is checked" (grant == manifest families == membership; a person's * widens nothing; a family is granted only once the manifest adds it), no durable consumer, node-tools only, parse refusals, and the kind/asker rule.
Delivery order: this pull request is delivered first. The mesh-tools pull request (mesh_wait, and node-tools' manifest declaring waits) follows only after this one is delivered, because until then the controller's strict manifest parser refuses waits.
Issue: [hq issue 745](../../hq/src/branch/main/04-ISSUES) (a session cannot hear the bus). Decision: novox/hq ADR 0367 (a session waits on the bus for an event instead of polling), version 13.
What it does:
- A new manifest word, `waits`: the event families a session may wait on through the mesh MCP server's `mesh_wait`. Only node-tools may declare it, one family at a time, never with a wildcard. Anything else is refused at parse.
- The inventory resolves each family the way `consumes` is resolved. A seat's event goes under the seat and a module's under the module. A family on a seat whose events end in a kind or an asker (such as `operator-channel.decided.claude-code`) must name that last token, and is refused at composition without it.
- The tool runner's account is granted a plain subscription on those subjects alone. No durable consumer is made for them, and nothing else widens the grant.
- The tool runner's membership names the same list (`waits`), which `mesh_wait` reads to refuse any other family.
Tests: the composition test from ADR 0367's "How it is checked" (grant == manifest families == membership; a person's `*` widens nothing; a family is granted only once the manifest adds it), no durable consumer, node-tools only, parse refusals, and the kind/asker rule.
Delivery order: this pull request is delivered first. The mesh-tools pull request (`mesh_wait`, and node-tools' manifest declaring `waits`) follows only after this one is delivered, because until then the controller's strict manifest parser refuses `waits`.
mesh/delivery covered after its failure: a later walk that contains it was delivered: plan-1792019685173332639 (novox/mesh-controller at 0b7e740b into ma…
A session on the mesh MCP server polls for every verdict, answer and delivery because the tool
runner's account hears no event. ADR 0367 lets the tool runner's module name, one by one, the
families a session may wait on: the manifest's `waits`, refused for any other module and for a
wildcard. The controller grants the runtime's account a plain subscription on those subjects
alone, makes no durable consumer for them, and issues the same list in the tool runner's
membership, so the grant and what `mesh_wait` offers come from one composition and no call or
setting widens it. A family on a seat whose events end in a kind or an asker must name it, and is
refused at composition without it, so it is never granted a subject nothing publishes on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deliverynovox/mesh-controller@755457cc379e — failed since 2026-10-14T23:14:58Z
Covered: covered after its failure: a later walk that contains it was delivered: plan-1792019685173332639 (novox/mesh-controller at 0b7e740b into main, done, contains its merge 0b7e740b)
Delivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
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
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 route-proxy, build-agent is judged on its first machine
Machines
mesh-controller on every machine running it: sent
route-proxy on every machine running it: sent
build-agent on every machine running it: sent
Transitions
2026-10-14 23:05 (new) → proposed (announced): novox/mesh-controller#342's head announced
2026-10-14 23:12 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
2026-10-14 23:12 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-14 23:14 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-14 23:14 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-14 23:14 delivering → failed (failed): its walk failed, carrying its own commit: a gate on a first machine (what it carried put back), a build, a machine
The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-controller@755457cc379e` — **failed** since 2026-10-14T23:14:58Z
**Covered**: covered after its failure: a later walk that contains it was delivered: plan-1792019685173332639 (novox/mesh-controller at 0b7e740b into main, done, contains its merge 0b7e740b)
**Delivery plan** — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller, route-proxy
- tier 1: build-agent
- ace: receives route-proxy, build-agent
- g14: receives build-agent
- novox: receives mesh-controller, route-proxy, build-agent
- shanks: receives build-agent
- 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
- 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 route-proxy, build-agent is judged on its first machine
**Machines**
- mesh-controller on every machine running it: sent
- route-proxy on every machine running it: sent
- build-agent on every machine running it: sent
**Transitions**
- 2026-10-14 23:05 (new) → proposed (announced): novox/mesh-controller#342's head announced
- 2026-10-14 23:12 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
- 2026-10-14 23:12 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-14 23:14 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-14 23:14 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-14 23:14 delivering → failed (failed): its walk failed, carrying its own commit: a gate on a first machine (what it carried put back), a build, a machine
The commit's note under `refs/notes/mesh-plan` keeps every transition: `git log --notes=mesh-plan`.
An independent review of issue 745 (mesh_wait, ADR 0367), mesh-controller half.
The tree is the reviewed tree. This head's tree is 85a9f0a91f, identical to the tree of b6efae49, which I reviewed locally. Its parent is origin/main 4cc6b6c5.
Checks I ran on b6efae49:gofmt -l (nothing listed), go vet ./..., go test ./... and merge-check.sh, all green, against a throwaway PostgreSQL. Each new test fails when the code it covers is reverted.
Three review rounds:
Round 1: a mesh_wait outlived a client that cancelled or hung up, for up to 10 minutes; a family on a kinded or caller-named seat was granted a subject nothing publishes on. Fixed in round 2: the request context is passed through and ends the wait and its subscription at once; such a family must name its kind or asker and is refused otherwise.
Round 2: stopping the tool runner waited for every mesh_wait in flight, up to 10 minutes. Fixed in round 3 (mesh-tools): closing the console cancels every request's context, with a 5-second Shutdown deadline as the backstop.
Round 3: no findings left. Clause 6 holds: the wait grant is exactly the tool runner's manifest families, with no wildcard and no durable consumer, and a person's * widens nothing.
Delivery order: merge and walk this pull request first, because the manifest parser on main refuses waits until it is delivered. Merge mesh-tools' pull request only after this one's walk is done, and only after mesh-delivery.recheck gives it a new verdict.
Verdict: APPROVE at 755457cc379e6eea647826512aaa14b1d745b2d8
An independent review of issue 745 (`mesh_wait`, ADR 0367), mesh-controller half.
**The tree is the reviewed tree.** This head's tree is 85a9f0a91f9a9213230a3a38d6b064b53e8ef725, identical to the tree of b6efae49, which I reviewed locally. Its parent is origin/main 4cc6b6c5.
**Checks I ran on b6efae49:** `gofmt -l` (nothing listed), `go vet ./...`, `go test ./...` and `merge-check.sh`, all green, against a throwaway PostgreSQL. Each new test fails when the code it covers is reverted.
**Three review rounds:**
1. Round 1: a mesh_wait outlived a client that cancelled or hung up, for up to 10 minutes; a family on a kinded or caller-named seat was granted a subject nothing publishes on. Fixed in round 2: the request context is passed through and ends the wait and its subscription at once; such a family must name its kind or asker and is refused otherwise.
2. Round 2: stopping the tool runner waited for every mesh_wait in flight, up to 10 minutes. Fixed in round 3 (mesh-tools): closing the console cancels every request's context, with a 5-second Shutdown deadline as the backstop.
3. Round 3: no findings left. Clause 6 holds: the wait grant is exactly the tool runner's manifest families, with no wildcard and no durable consumer, and a person's `*` widens nothing.
**Delivery order:** merge and walk this pull request first, because the manifest parser on main refuses `waits` until it is delivered. Merge mesh-tools' pull request only after this one's walk is done, and only after `mesh-delivery.recheck` gives it a new verdict.
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
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 route-proxy, build-agent is judged on its first machine
read by no module's build: internal/broker/waits_test.go, internal/catalogue/waits_test.go, internal/inventory/waits_grants_test.go
Run by the build seat on novox as build-1792019136776647679 (builds --log build-1792019136776647679).
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 60 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-14T22:54:08Z 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-14T22:54:08Z
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 2 tier(s): build-agent, mesh-controller, route-proxy
notes:
- internal/broker/waits_test.go, internal/catalogue/waits_test.go and internal/inventory/waits_grants_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.857s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.136s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.216s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.151s
ok github.com/novox/mesh-controller/examples/route-proxy 1.524s
ok github.com/novox/mesh-controller/internal/artifacts 1.244s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 17.181s
ok github.com/novox/mesh-controller/internal/catalogue 45.602s
ok github.com/novox/mesh-controller/internal/conditions 7.589s
ok github.com/novox/mesh-controller/internal/envfile 1.208s
ok github.com/novox/mesh-controller/internal/facts 1.218s
ok github.com/novox/mesh-controller/internal/identity 34.235s
ok github.com/novox/mesh-controller/internal/lease 11.006s
ok github.com/novox/mesh-controller/internal/licences 27.744s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.097s
ok github.com/novox/mesh-controller/internal/lint 9.975s
ok github.com/novox/mesh-controller/internal/outward 1.247s
ok github.com/novox/mesh-controller/internal/overlay 1.373s
ok github.com/novox/mesh-controller/internal/secrets 3.104s
ok github.com/novox/mesh-controller/internal/store 11.282s
ok github.com/novox/mesh-controller/internal/testbus 2.582s
ok github.com/novox/mesh-controller/internal/token 1.290s
ok github.com/novox/mesh-controller/cmd/mesh-controller 80s (shard 1 of 8: 117 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 76s (shard 2 of 8: 117 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 104s (shard 3 of 8: 117 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 88s (shard 4 of 8: 117 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 80s (shard 5 of 8: 116 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 86s (shard 6 of 8: 116 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 78s (shard 7 of 8: 116 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 76s (shard 8 of 8: 116 tests)
ok github.com/novox/mesh-controller/internal/inventory 66s (shard 1 of 4: 69 tests)
ok github.com/novox/mesh-controller/internal/inventory 65s (shard 2 of 4: 69 tests)
ok github.com/novox/mesh-controller/internal/inventory 69s (shard 3 of 4: 69 tests)
ok github.com/novox/mesh-controller/internal/inventory 69s (shard 4 of 4: 68 tests)
ok github.com/novox/mesh-controller/internal/builder 122s (shard 1 of 4: 52 tests)
ok github.com/novox/mesh-controller/internal/builder 69s (shard 2 of 4: 51 tests)
ok github.com/novox/mesh-controller/internal/builder 104s (shard 3 of 4: 51 tests)
ok github.com/novox/mesh-controller/internal/builder 88s (shard 4 of 4: 51 tests)
ok github.com/novox/mesh-controller/internal/link 25s (shard 1 of 4: 44 tests)
ok github.com/novox/mesh-controller/internal/link 36s (shard 2 of 4: 44 tests)
ok github.com/novox/mesh-controller/internal/link 42s (shard 3 of 4: 44 tests)
ok github.com/novox/mesh-controller/internal/link 35s (shard 4 of 4: 44 tests)
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (1.26s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (1.23s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (1.18s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (1.17s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (1.13s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (1.32s)
./cmd/mesh-controller --- PASS: TestAPlanFollowedFromTheStoreAnswersWhenItMoves (3.33s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (1.95s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.56s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (3.09s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (1.81s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (1.11s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (1.35s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (0.98s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.84s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (1.14s)
./cmd/mesh-controller --- PASS: TestReplay237 (1.44s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (1.47s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (2.61s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (1.84s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (1.15s)
./cmd/mesh-controller --- PASS: TestTheSendMakesNoValueForAnOutsideSecretNobodyGave (3.98s)
./cmd/mesh-controller --- PASS: TestAQuestionComposesWithoutAnOutsideSecretNobodyGave (3.43s)
./cmd/mesh-controller --- PASS: TestReplay201 (1.55s)
./cmd/mesh-controller --- PASS: TestARollbackWhoseSendWasRefusedIsCompletedByTheNextSend (0.94s)
./cmd/mesh-controller --- PASS: TestAGateJudgesTheOtherMovesBesideAKeptCore (0.53s)
./cmd/mesh-controller --- PASS: TestReplay401 (4.88s)
./cmd/mesh-controller --- PASS: TestReplay201ThePlansSend (2.52s)
./cmd/mesh-controller --- PASS: TestPlanAndNodeListAnOptionalRequirementLeftUnbound (1.80s)
./cmd/mesh-controller --- PASS: TestReplay340 (1.12s)
./cmd/mesh-controller --- PASS: TestOnlyATrustedFilesNamedKeyIsRefusedThroughAVerb (0.84s)
./cmd/mesh-controller --- PASS: TestReplay349 (0.66s)
./cmd/mesh-controller --- PASS: TestReplay348AFaultFromBeforeTheSendFailsNoGate (0.68s)
./cmd/mesh-controller --- PASS: TestReplay239AModuleNameIsNotTakenOverByAnotherRepository (0.85s)
./cmd/mesh-controller --- PASS: TestAWalkThatMovedNothingSaysWhichModulesMatchedWhatRuns (2.61s)
./cmd/mesh-controller --- PASS: TestAWalkWhoseEveryBuildCameOutTheSameIsDone (0.65s)
./cmd/mesh-controller --- PASS: TestReplay614ANewSDKPlansTheToolchainAndThenItsBundles (0.97s)
./cmd/mesh-controller --- PASS: TestOneAcceptForAProviderIsPlacedForEveryConsumer (4.16s)
./cmd/mesh-controller --- PASS: TestReplay164 (3.80s)
./cmd/mesh-controller --- PASS: TestAnApprovedLayerOpensTheWalkThatSendsIt (3.29s)
./cmd/mesh-controller --- PASS: TestASettingsWalkSendsOneMachineAtATimeEachJudged (1.67s)
./cmd/mesh-controller --- PASS: TestAFailedSettingsWalkStopsAndHoldsNothingBack (1.03s)
./cmd/mesh-controller --- PASS: TestASettingsWalkSendsTheLayerAloneEveryBuildKept (1.84s)
./cmd/mesh-controller --- PASS: TestASettingsWalkStopsBeforeADataMoveAndPassesOverAMachineAway (3.27s)
./cmd/mesh-controller --- PASS: TestACrossingSendSupersedesASettingsGate (1.07s)
./cmd/mesh-controller --- PASS: TestASettingsWalkFailsOnARefusalThatCannotClear (1.12s)
./cmd/mesh-controller --- PASS: TestAProviderElsewhereServesItsOwnComposedName (0.80s)
./cmd/mesh-controller --- PASS: TestAReusedCheckBuildIsRegisteredByItsDigestAndGatedAsABuiltOne (1.32s)
./cmd/mesh-controller --- PASS: TestAReleaseSendsTheRestAtOnceAfterTheFirstPasses (3.57s)
./cmd/mesh-controller --- PASS: TestARestMachineThatFailsIsPutBackAloneAndTheOthersAreJudgedOn (1.90s)
./cmd/mesh-controller --- PASS: TestAWalkTakesOverTheReadingsOfAGateJudgingTheSameBuildThere (0.87s)
./cmd/mesh-controller --- PASS: TestAFirstSendMadeAndNotKeptIsNotSentAgain (1.22s)
./cmd/mesh-controller --- PASS: TestAReleaseSendKeptAndMadeIsNotMadeAgain (1.17s)
./cmd/mesh-controller --- PASS: TestAFirstMachineThatFailsStillStopsTheWalk (0.94s)
./cmd/mesh-controller --- PASS: TestTheControlNodeIsSentLastInAStep (1.07s)
./cmd/mesh-controller --- PASS: TestARestMachineSilentPastItsBoundIsLeftAndSaid (0.91s)
./cmd/mesh-controller --- PASS: TestANoMoveTierWaitsForNoNewReport (3.70s)
./cmd/mesh-controller --- PASS: TestOneProviderDownAndThreeConsumersFailingAreOneCondition (1.32s)
./cmd/mesh-controller --- PASS: TestAConsumerFailingBesideAHealthyProviderIsItsOwn (1.05s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.25s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.23s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.35s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.28s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.19s)
./internal/inventory --- PASS: TestAPlanIdHoldingAQuoteIsReadAsAPlainId (0.16s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.19s)
./internal/inventory --- PASS: TestAWalksRestIsReadFromEachMachinesOwnSend (0.16s)
./internal/inventory --- PASS: TestAStoredBuildWithASilentMergeableFileIsStillReadAndComposed (0.12s)
./internal/inventory --- PASS: TestACredentialIssuedOutsideIsNeverMade (0.28s)
./internal/inventory --- PASS: TestOneAcceptForAProviderIsSealedToEveryConsumer (0.22s)
./internal/inventory --- PASS: TestASharedOwnSecretIssuedOutsideIsNeverMade (0.14s)
./internal/inventory --- PASS: TestAReportOfABusyContainerIsKeptAndReadBack (1.00s)
./internal/inventory --- PASS: TestWhatRunsIsTheRegisteredBuildNotANewerOnePutBack (0.28s)
**Merge check** at `755457cc`
Judged: head `755457cc379e` merged into trunk `4cc6b6c566a5`; read beside it: mesh-catalog `9492278d934b`, mesh-controller-main `4cc6b6c566a5`, mesh-host `198fd34ec497`, mesh-tools `5d70eb3e35a9`
- `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, route-proxy
- tier 1: build-agent
- ace: receives route-proxy, build-agent
- g14: receives build-agent
- novox: receives mesh-controller, route-proxy, build-agent
- shanks: receives build-agent
- 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
- 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 route-proxy, build-agent is judged on its first machine
- read by no module's build: internal/broker/waits_test.go, internal/catalogue/waits_test.go, internal/inventory/waits_grants_test.go
Run by the build seat on novox as `build-1792019136776647679` (`builds --log build-1792019136776647679`).
```
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 60 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-14T22:54:08Z 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-14T22:54:08Z
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 2 tier(s): build-agent, mesh-controller, route-proxy
notes:
- internal/broker/waits_test.go, internal/catalogue/waits_test.go and internal/inventory/waits_grants_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.857s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.136s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.216s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.151s
ok github.com/novox/mesh-controller/examples/route-proxy 1.524s
ok github.com/novox/mesh-controller/internal/artifacts 1.244s
? github.com/novox/mesh-controller/internal/beside [no test files]
ok github.com/novox/mesh-controller/internal/broker 17.181s
ok github.com/novox/mesh-controller/internal/catalogue 45.602s
ok github.com/novox/mesh-controller/internal/conditions 7.589s
ok github.com/novox/mesh-controller/internal/envfile 1.208s
ok github.com/novox/mesh-controller/internal/facts 1.218s
ok github.com/novox/mesh-controller/internal/identity 34.235s
ok github.com/novox/mesh-controller/internal/lease 11.006s
ok github.com/novox/mesh-controller/internal/licences 27.744s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.097s
ok github.com/novox/mesh-controller/internal/lint 9.975s
ok github.com/novox/mesh-controller/internal/outward 1.247s
ok github.com/novox/mesh-controller/internal/overlay 1.373s
ok github.com/novox/mesh-controller/internal/secrets 3.104s
ok github.com/novox/mesh-controller/internal/store 11.282s
ok github.com/novox/mesh-controller/internal/testbus 2.582s
ok github.com/novox/mesh-controller/internal/token 1.290s
ok github.com/novox/mesh-controller/cmd/mesh-controller 80s (shard 1 of 8: 117 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 76s (shard 2 of 8: 117 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 104s (shard 3 of 8: 117 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 88s (shard 4 of 8: 117 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 80s (shard 5 of 8: 116 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 86s (shard 6 of 8: 116 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 78s (shard 7 of 8: 116 tests)
ok github.com/novox/mesh-controller/cmd/mesh-controller 76s (shard 8 of 8: 116 tests)
ok github.com/novox/mesh-controller/internal/inventory 66s (shard 1 of 4: 69 tests)
ok github.com/novox/mesh-controller/internal/inventory 65s (shard 2 of 4: 69 tests)
ok github.com/novox/mesh-controller/internal/inventory 69s (shard 3 of 4: 69 tests)
ok github.com/novox/mesh-controller/internal/inventory 69s (shard 4 of 4: 68 tests)
ok github.com/novox/mesh-controller/internal/builder 122s (shard 1 of 4: 52 tests)
ok github.com/novox/mesh-controller/internal/builder 69s (shard 2 of 4: 51 tests)
ok github.com/novox/mesh-controller/internal/builder 104s (shard 3 of 4: 51 tests)
ok github.com/novox/mesh-controller/internal/builder 88s (shard 4 of 4: 51 tests)
ok github.com/novox/mesh-controller/internal/link 25s (shard 1 of 4: 44 tests)
ok github.com/novox/mesh-controller/internal/link 36s (shard 2 of 4: 44 tests)
ok github.com/novox/mesh-controller/internal/link 42s (shard 3 of 4: 44 tests)
ok github.com/novox/mesh-controller/internal/link 35s (shard 4 of 4: 44 tests)
store tests, each run against the store:
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeWalksTheOthersAgain (1.26s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeEndsTheMergesThatContainIt (1.23s)
./cmd/mesh-controller --- PASS: TestAStopWalksTheOthersAgainInTheOpenBatch (1.18s)
./cmd/mesh-controller --- PASS: TestAStopNamesWhatStaysOnTheMachinesAndWhatStillCarriesIt (1.17s)
./cmd/mesh-controller --- PASS: TestAStopWithoutAMergeLeavesItOutOfABatch (1.13s)
./cmd/mesh-controller --- PASS: TestSavingPlansAndMovingMergesIsOneAct (1.32s)
./cmd/mesh-controller --- PASS: TestAPlanFollowedFromTheStoreAnswersWhenItMoves (3.33s)
./cmd/mesh-controller --- PASS: TestNodeShowAndStatusReadTheLastSendFromTheStore (1.95s)
./cmd/mesh-controller --- PASS: TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds (0.56s)
./cmd/mesh-controller --- PASS: TestAWalkLetGoAndStoppedByVerbsIsSaidStartedAndEnded (3.09s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedOrClosedByAPersonIsSaidEndedStopped (1.81s)
./cmd/mesh-controller --- PASS: TestAWalkRetriedByAPersonIsSaidStartedAgain (1.11s)
./cmd/mesh-controller --- PASS: TestABacklogReleasedByAPersonIsSaidStarted (1.35s)
./cmd/mesh-controller --- PASS: TestAWalkEndedByCancelOrClearIsSaidEnded (0.98s)
./cmd/mesh-controller --- PASS: TestAWalkRestartedByARebuildIsSaidStarted (0.84s)
./cmd/mesh-controller --- PASS: TestAWalkStoppedByHandAndRetriedEndsFailedWhenItFailsAgain (1.14s)
./cmd/mesh-controller --- PASS: TestReplay237 (1.44s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeUnresolvedSaysSoOnceInItsAnswer (1.47s)
./cmd/mesh-controller --- PASS: TestAnUnassignThatLeavesItsNodeResolvedSaysNothingOfIt (2.61s)
./cmd/mesh-controller --- PASS: TestAnAssignThatLeavesItsNodeUnresolvedSaysOnlyThePlansRefusal (1.84s)
./cmd/mesh-controller --- PASS: TestADirectoryOwnersKeyIsRefusedThroughAVerb (1.15s)
./cmd/mesh-controller --- PASS: TestTheSendMakesNoValueForAnOutsideSecretNobodyGave (3.98s)
./cmd/mesh-controller --- PASS: TestAQuestionComposesWithoutAnOutsideSecretNobodyGave (3.43s)
./cmd/mesh-controller --- PASS: TestReplay201 (1.55s)
./cmd/mesh-controller --- PASS: TestARollbackWhoseSendWasRefusedIsCompletedByTheNextSend (0.94s)
./cmd/mesh-controller --- PASS: TestAGateJudgesTheOtherMovesBesideAKeptCore (0.53s)
./cmd/mesh-controller --- PASS: TestReplay401 (4.88s)
./cmd/mesh-controller --- PASS: TestReplay201ThePlansSend (2.52s)
./cmd/mesh-controller --- PASS: TestPlanAndNodeListAnOptionalRequirementLeftUnbound (1.80s)
./cmd/mesh-controller --- PASS: TestReplay340 (1.12s)
./cmd/mesh-controller --- PASS: TestOnlyATrustedFilesNamedKeyIsRefusedThroughAVerb (0.84s)
./cmd/mesh-controller --- PASS: TestReplay349 (0.66s)
./cmd/mesh-controller --- PASS: TestReplay348AFaultFromBeforeTheSendFailsNoGate (0.68s)
./cmd/mesh-controller --- PASS: TestReplay239AModuleNameIsNotTakenOverByAnotherRepository (0.85s)
./cmd/mesh-controller --- PASS: TestAWalkThatMovedNothingSaysWhichModulesMatchedWhatRuns (2.61s)
./cmd/mesh-controller --- PASS: TestAWalkWhoseEveryBuildCameOutTheSameIsDone (0.65s)
./cmd/mesh-controller --- PASS: TestReplay614ANewSDKPlansTheToolchainAndThenItsBundles (0.97s)
./cmd/mesh-controller --- PASS: TestOneAcceptForAProviderIsPlacedForEveryConsumer (4.16s)
./cmd/mesh-controller --- PASS: TestReplay164 (3.80s)
./cmd/mesh-controller --- PASS: TestAnApprovedLayerOpensTheWalkThatSendsIt (3.29s)
./cmd/mesh-controller --- PASS: TestASettingsWalkSendsOneMachineAtATimeEachJudged (1.67s)
./cmd/mesh-controller --- PASS: TestAFailedSettingsWalkStopsAndHoldsNothingBack (1.03s)
./cmd/mesh-controller --- PASS: TestASettingsWalkSendsTheLayerAloneEveryBuildKept (1.84s)
./cmd/mesh-controller --- PASS: TestASettingsWalkStopsBeforeADataMoveAndPassesOverAMachineAway (3.27s)
./cmd/mesh-controller --- PASS: TestACrossingSendSupersedesASettingsGate (1.07s)
./cmd/mesh-controller --- PASS: TestASettingsWalkFailsOnARefusalThatCannotClear (1.12s)
./cmd/mesh-controller --- PASS: TestAProviderElsewhereServesItsOwnComposedName (0.80s)
./cmd/mesh-controller --- PASS: TestAReusedCheckBuildIsRegisteredByItsDigestAndGatedAsABuiltOne (1.32s)
./cmd/mesh-controller --- PASS: TestAReleaseSendsTheRestAtOnceAfterTheFirstPasses (3.57s)
./cmd/mesh-controller --- PASS: TestARestMachineThatFailsIsPutBackAloneAndTheOthersAreJudgedOn (1.90s)
./cmd/mesh-controller --- PASS: TestAWalkTakesOverTheReadingsOfAGateJudgingTheSameBuildThere (0.87s)
./cmd/mesh-controller --- PASS: TestAFirstSendMadeAndNotKeptIsNotSentAgain (1.22s)
./cmd/mesh-controller --- PASS: TestAReleaseSendKeptAndMadeIsNotMadeAgain (1.17s)
./cmd/mesh-controller --- PASS: TestAFirstMachineThatFailsStillStopsTheWalk (0.94s)
./cmd/mesh-controller --- PASS: TestTheControlNodeIsSentLastInAStep (1.07s)
./cmd/mesh-controller --- PASS: TestARestMachineSilentPastItsBoundIsLeftAndSaid (0.91s)
./cmd/mesh-controller --- PASS: TestANoMoveTierWaitsForNoNewReport (3.70s)
./cmd/mesh-controller --- PASS: TestOneProviderDownAndThreeConsumersFailingAreOneCondition (1.32s)
./cmd/mesh-controller --- PASS: TestAConsumerFailingBesideAHealthyProviderIsItsOwn (1.05s)
./internal/inventory --- PASS: TestTheLastSendSaysWhatTheMachineAnswered (0.25s)
./internal/inventory --- PASS: TestAReportIsTheLastSendsAnswerOnlyWhenItIsAboutThatSend (0.23s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain (0.35s)
./internal/inventory --- PASS: TestAnIssuedValueIsSealedAgainAfterAKeyChangeOrAnAcceptance (0.28s)
./internal/inventory --- PASS: TestAConditionsLooksAreKeptBesideTheBucket (0.19s)
./internal/inventory --- PASS: TestAPlanIdHoldingAQuoteIsReadAsAPlainId (0.16s)
./internal/inventory --- PASS: TestAWalksStartIsKeptAndARefusedSaveLeavesItUnsaid (0.19s)
./internal/inventory --- PASS: TestAWalksRestIsReadFromEachMachinesOwnSend (0.16s)
./internal/inventory --- PASS: TestAStoredBuildWithASilentMergeableFileIsStillReadAndComposed (0.12s)
./internal/inventory --- PASS: TestACredentialIssuedOutsideIsNeverMade (0.28s)
./internal/inventory --- PASS: TestOneAcceptForAProviderIsSealedToEveryConsumer (0.22s)
./internal/inventory --- PASS: TestASharedOwnSecretIssuedOutsideIsNeverMade (0.14s)
./internal/inventory --- PASS: TestAReportOfABusyContainerIsKeptAndReadBack (1.00s)
./internal/inventory --- PASS: TestWhatRunsIsTheRegisteredBuildNotANewerOnePutBack (0.28s)
```
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.
Issue: hq issue 745 (a session cannot hear the bus). Decision: novox/hq ADR 0367 (a session waits on the bus for an event instead of polling), version 13.
What it does:
waits: the event families a session may wait on through the mesh MCP server'smesh_wait. Only node-tools may declare it, one family at a time, never with a wildcard. Anything else is refused at parse.consumesis resolved. A seat's event goes under the seat and a module's under the module. A family on a seat whose events end in a kind or an asker (such asoperator-channel.decided.claude-code) must name that last token, and is refused at composition without it.waits), whichmesh_waitreads to refuse any other family.Tests: the composition test from ADR 0367's "How it is checked" (grant == manifest families == membership; a person's
*widens nothing; a family is granted only once the manifest adds it), no durable consumer, node-tools only, parse refusals, and the kind/asker rule.Delivery order: this pull request is delivered first. The mesh-tools pull request (
mesh_wait, and node-tools' manifest declaringwaits) follows only after this one is delivered, because until then the controller's strict manifest parser refuseswaits.Delivery
novox/mesh-controller@755457cc379e— failed since 2026-10-14T23:14:58ZCovered: covered after its failure: a later walk that contains it was delivered: plan-1792019685173332639 (novox/mesh-controller at
0b7e740binto main, done, contains its merge0b7e740b)Delivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Machines
Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Verdict: APPROVE at
755457cc37An independent review of issue 745 (
mesh_wait, ADR 0367), mesh-controller half.The tree is the reviewed tree. This head's tree is
85a9f0a91f, identical to the tree of b6efae49, which I reviewed locally. Its parent is origin/main4cc6b6c5.Checks I ran on b6efae49:
gofmt -l(nothing listed),go vet ./...,go test ./...andmerge-check.sh, all green, against a throwaway PostgreSQL. Each new test fails when the code it covers is reverted.Three review rounds:
*widens nothing.Delivery order: merge and walk this pull request first, because the manifest parser on main refuses
waitsuntil it is delivered. Merge mesh-tools' pull request only after this one's walk is done, and only aftermesh-delivery.recheckgives it a new verdict.Merge check at
755457ccJudged: head
755457cc379emerged into trunk4cc6b6c566a5; read beside it: mesh-catalog9492278d934b, mesh-controller-main4cc6b6c566a5, mesh-host198fd34ec497, mesh-tools5d70eb3e35a9mesh/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 novox as
build-1792019136776647679(builds --log build-1792019136776647679).