The desktop popups were walls of ids in UTC, and the first rewording still left the operator asking whether to act and how without a session.
messenger
Title is the condition's headline; body is its explanation, opened by the verdict ("Nothing for you to do." or "Needs you:" and one thing the operator does), then since when in the operator's zone (new setting time-zone).
A warning that needs nothing is not sent: kept open, marked quiet in the history, said when it becomes urgent or its words say "Needs you:".
Answers: each condition's actions (Release, Stop, Start, Restart, Silence for a week) plus Details are offered on the desk; the chosen token comes back as dunst.action-chosen, the messenger calls the action's seat verb with a why naming the operator, channel and label, and edits the notification with the outcome. Details shows summary, key and since when on the asking machine. A message with answers never goes into a digest. Telegram: words only for now.
Manifest: consumes dunst.action-chosen; invokes mesh-delivery.release, mesh-delivery.stop, mesh-controller.plans, node-service-manager.restart besides what it had.
Clearance is one line; no key, id, commit, verb or markup in any message.
dunst (holder of node-notifier)
send takes actions (token, label, at most 4): notify-send --wait --action=..., the id answered at once, the chosen token said later as the module event action-chosen {id, token, machine}. Nothing is said for a notification closed without an answer.
Tests: messenger/.../words_test.go (the real notifications of hq issue 320: quiet or shown, exact title/body/answers, the exact verb and arguments an answer calls, one-line clearance; a quiet warning said when urgent; Details), dunst/.../actions_test.go. merge-check.sh with both modules passes here (race on); the branch's controller checks both manifests ok.
Goes with novox/mesh-controller #141 and novox/hq #203. Deliver the controller first.
The desktop popups were walls of ids in UTC, and the first rewording still left the operator asking whether to act and how without a session.
**messenger**
- Title is the condition's headline; body is its explanation, opened by the verdict ("Nothing for you to do." or "Needs you:" and one thing the operator does), then since when in the operator's zone (new setting `time-zone`).
- **A warning that needs nothing is not sent**: kept open, marked quiet in the history, said when it becomes urgent or its words say "Needs you:".
- **Answers**: each condition's actions (Release, Stop, Start, Restart, Silence for a week) plus Details are offered on the desk; the chosen token comes back as `dunst.action-chosen`, the messenger calls the action's seat verb with a why naming the operator, channel and label, and edits the notification with the outcome. Details shows summary, key and since when on the asking machine. A message with answers never goes into a digest. Telegram: words only for now.
- Manifest: consumes `dunst.action-chosen`; invokes `mesh-delivery.release`, `mesh-delivery.stop`, `mesh-controller.plans`, `node-service-manager.restart` besides what it had.
- Clearance is one line; no key, id, commit, verb or markup in any message.
**dunst** (holder of `node-notifier`)
- `send` takes `actions` (token, label, at most 4): `notify-send --wait --action=...`, the id answered at once, the chosen token said later as the module event `action-chosen` {id, token, machine}. Nothing is said for a notification closed without an answer.
Tests: `messenger/.../words_test.go` (the real notifications of hq issue 320: quiet or shown, exact title/body/answers, the exact verb and arguments an answer calls, one-line clearance; a quiet warning said when urgent; Details), `dunst/.../actions_test.go`. `merge-check.sh` with both modules passes here (race on); the branch's controller checks both manifests ok.
Goes with novox/mesh-controller #141 and novox/hq #203. Deliver the controller first.
The desktop popups were walls of plan ids, commits, keys and verb syntax in UTC.
The messenger now shows the condition's headline, explanation and resolved line,
since when in the operator's time zone, and a clearance in one line (hq ADR 0253).
composed together: pass — every machine composes with the change as it did without (4 of 4 compose)
Machines
build-agent on g14: passed — carried by plan-1791462035870045881
route-proxy on ace: passed — carried by plan-1791462035870045881
dunst on g14: passed — healthy 3 times over 2m25s
messenger on novox: passed — healthy 3 times over 2m11s
dunst on the rest running it: sent
messenger on the rest running it: sent
Transitions
2026-10-08 12:01 (new) → proposed (announced): novox/mesh-catalog#126's head announced
2026-10-08 12:02 proposed → checked (checked): the verdict names this commit
2026-10-08 12:02 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-08 12:21 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-08 12:35 published → delivering (go): its walk started: let go by this owner in its group's order, by a person, or on the controller's own path
2026-10-08 12:38 delivering → delivered (done): its walk is done: every machine of its deploy plan passed, or was left as its policy says
The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-catalog@f00b5a19b1be` — **delivered** since 2026-10-08T12:38:39Z
**Delivery plan** — builds dunst, messenger → g14, novox, shanks; no bus step
- tier 0: dunst, messenger
- g14: receives dunst
- novox: receives messenger
- shanks: receives dunst
**Group** `feat/plain-notifications`, in order: novox/hq@356c5f23f441 → novox/mesh-controller@1a4305213d08 → novox/mesh-catalog@f00b5a19b1be
- novox/mesh-controller@1a4305213d08 before novox/mesh-catalog@f00b5a19b1be: built by
- composed together: pass — every machine composes with the change as it did without (4 of 4 compose)
**Machines**
- build-agent on g14: passed — carried by plan-1791462035870045881
- route-proxy on ace: passed — carried by plan-1791462035870045881
- dunst on g14: passed — healthy 3 times over 2m25s
- messenger on novox: passed — healthy 3 times over 2m11s
- dunst on the rest running it: sent
- messenger on the rest running it: sent
**Transitions**
- 2026-10-08 12:01 (new) → proposed (announced): novox/mesh-catalog#126's head announced
- 2026-10-08 12:02 proposed → checked (checked): the verdict names this commit
- 2026-10-08 12:02 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-08 12:21 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-08 12:35 published → delivering (go): its walk started: let go by this owner in its group's order, by a person, or on the controller's own path
- 2026-10-08 12:38 delivering → delivered (done): its walk is done: every machine of its deploy plan passed, or was left as its policy says
The commit's note under `refs/notes/mesh-plan` keeps every transition: `git log --notes=mesh-plan`.
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: messenger)
mesh/repo-check: PASS — its merge-check.sh passed
Delivery plan — builds messenger → novox; no bus step
tier 0: messenger
novox: receives messenger
Run by the build seat on novox as build-1791458987612051434 (builds --log build-1791458987612051434).
--- the gate: messenger
messenger: ok, 4 tool(s), invokes seat:node-notifier.send, seat:mesh-controller.conditions, keeps state open, sent
long-running resources without health: 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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-08T11:21:31Z 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-08T11:21:31Z
modules the change moves:
- messenger (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 1 module(s) in 1 tier(s): messenger
--- its merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-catalog/checks/words 0.002s
words: 12 retired words, none in the 29623 strings of 546 files
long-running resources without health: 70, as kept
testing modules/messenger
ok messenger/cmd/messenger 1.400s
**Merge check** at `a6296dfd`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: messenger)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Delivery plan** — builds messenger → novox; no bus step
- tier 0: messenger
- novox: receives messenger
Run by the build seat on novox as `build-1791458987612051434` (`builds --log build-1791458987612051434`).
```
--- the gate: messenger
messenger: ok, 4 tool(s), invokes seat:node-notifier.send, seat:mesh-controller.conditions, keeps state open, sent
long-running resources without health: 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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-08T11:21:31Z 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-08T11:21:31Z
modules the change moves:
- messenger (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 1 module(s) in 1 tier(s): messenger
--- its merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-catalog/checks/words 0.002s
words: 12 retired words, none in the 29623 strings of 546 files
long-running resources without health: 70, as kept
testing modules/messenger
ok messenger/cmd/messenger 1.400s
```
mesh/merge-gate pass: builds dunst, messenger → g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
The operator could not tell from a notification whether to act, nor act without
opening a session. Each message now opens with a verdict, a warning that needs
nothing is not sent, and a notification offers answers the messenger performs
through their seat verbs; dunst's send gains actions and says the chosen one
(hq ADR 0253).
mesh-admin
changed title from messenger: say each notification in plain words, in the operator's time (hq ADR 0253, issue 320) to messenger and dunst: plain notifications that say whether you are needed, and take the answer from the desk (hq ADR 0253, issue 320)2026-10-08 12:00:52 +00:00
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: dunst, messenger)
mesh/repo-check: PASS — its merge-check.sh passed
Delivery plan — builds dunst, messenger → g14, novox, shanks; no bus step
tier 0: dunst, messenger
g14: receives dunst
novox: receives messenger
shanks: receives dunst
Run by the build seat on ace as build-1791460863849931396 (builds --log build-1791460863849931396).
--- the gate: dunst, messenger
dunst: ok, 5 tool(s)
messenger: ok, 4 tool(s), invokes seat:node-notifier.send, seat:mesh-controller.conditions, seat:mesh-delivery.release, seat:mesh-delivery.stop, seat:mesh-controller.plans, seat:node-service-manager.restart, keeps state open, sent
long-running resources without health: 0
2 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 2 module(s) changed against 4 machine(s), as the snapshot of 2026-10-08T11:31:31Z 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-08T11:31:31Z
modules the change moves:
- dunst (changed)
- messenger (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 1 tier(s): dunst, messenger
--- its merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-catalog/checks/words 0.002s
words: 12 retired words, none in the 29772 strings of 548 files
long-running resources without health: 70, as kept
testing modules/dunst
ok dunst/cmd/dunst-tools 2.042s
testing modules/messenger
ok messenger/cmd/messenger 1.319s
**Merge check** at `f00b5a19`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: dunst, messenger)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Delivery plan** — builds dunst, messenger → g14, novox, shanks; no bus step
- tier 0: dunst, messenger
- g14: receives dunst
- novox: receives messenger
- shanks: receives dunst
Run by the build seat on ace as `build-1791460863849931396` (`builds --log build-1791460863849931396`).
```
--- the gate: dunst, messenger
dunst: ok, 5 tool(s)
messenger: ok, 4 tool(s), invokes seat:node-notifier.send, seat:mesh-controller.conditions, seat:mesh-delivery.release, seat:mesh-delivery.stop, seat:mesh-controller.plans, seat:node-service-manager.restart, keeps state open, sent
long-running resources without health: 0
2 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 2 module(s) changed against 4 machine(s), as the snapshot of 2026-10-08T11:31:31Z 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-08T11:31:31Z
modules the change moves:
- dunst (changed)
- messenger (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 1 tier(s): dunst, messenger
--- its merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-catalog/checks/words 0.002s
words: 12 retired words, none in the 29772 strings of 548 files
long-running resources without health: 70, as kept
testing modules/dunst
ok dunst/cmd/dunst-tools 2.042s
testing modules/messenger
ok messenger/cmd/messenger 1.319s
```
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The desktop popups were walls of ids in UTC, and the first rewording still left the operator asking whether to act and how without a session.
messenger
time-zone).dunst.action-chosen, the messenger calls the action's seat verb with a why naming the operator, channel and label, and edits the notification with the outcome. Details shows summary, key and since when on the asking machine. A message with answers never goes into a digest. Telegram: words only for now.dunst.action-chosen; invokesmesh-delivery.release,mesh-delivery.stop,mesh-controller.plans,node-service-manager.restartbesides what it had.dunst (holder of
node-notifier)sendtakesactions(token, label, at most 4):notify-send --wait --action=..., the id answered at once, the chosen token said later as the module eventaction-chosen{id, token, machine}. Nothing is said for a notification closed without an answer.Tests:
messenger/.../words_test.go(the real notifications of hq issue 320: quiet or shown, exact title/body/answers, the exact verb and arguments an answer calls, one-line clearance; a quiet warning said when urgent; Details),dunst/.../actions_test.go.merge-check.shwith both modules passes here (race on); the branch's controller checks both manifests ok.Goes with novox/mesh-controller #141 and novox/hq #203. Deliver the controller first.
Delivery
novox/mesh-catalog@f00b5a19b1be— delivered since 2026-10-08T12:38:39ZDelivery plan — builds dunst, messenger → g14, novox, shanks; no bus step
Group
feat/plain-notifications, in order: novox/hq@356c5f23f4 → novox/mesh-controller@1a4305213d → novox/mesh-catalog@f00b5a19b1Machines
Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Merge check at
a6296dfdmesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: messenger)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds messenger → novox; no bus step
Run by the build seat on novox as
build-1791458987612051434(builds --log build-1791458987612051434).messenger: say each notification in plain words, in the operator's time (hq ADR 0253, issue 320)to messenger and dunst: plain notifications that say whether you are needed, and take the answer from the desk (hq ADR 0253, issue 320)Merge check at
f00b5a19mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: dunst, messenger)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds dunst, messenger → g14, novox, shanks; no bus step
Run by the build seat on ace as
build-1791460863849931396(builds --log build-1791460863849931396).