Feature feat/mail-seats (playbook 07), one delivery group with novox/mesh-controller and novox/mesh-host.
after: novox/mesh-controller
Issue 800 (ADR 0378 as amended by ADR 0379): mesh-mail declares mail-store, mail-webclient and mail-notifier (node scope, needs node-notifier) and claims mail-store (mail-store.accounts/search/read/send); checks/mailstore refuses any other claimant of mail-store. New module mesh-mail-notifier (runs-as its own account, consumes mesh-mail's added events, claims mail-notifier): shows each new inbox mail once per machine through node-notifier.send; quiet for read mail, own address, other folders and first sync; more than three in a minute folded; failed notices retried; emits shown.
Issue 797 (ADR 0380 §8): messenger's operator-channel gains tell: one plain message, every channel once, never held or escalated, only Details, its own cap.
Needs mesh-controller's needs field (issue 802), hence after: above.
Reviewed locally: rounds 1 to 3 changes, round 4 approved at c2cd2e1. merge-check.sh green with MESH_GATE built from mesh-controller feat/mail-seats (health count 62). Follow-ups: 839, 841.
Feature feat/mail-seats (playbook 07), one delivery group with novox/mesh-controller and novox/mesh-host.
after: novox/mesh-controller
- Issue 800 (ADR 0378 as amended by ADR 0379): mesh-mail declares mail-store, mail-webclient and mail-notifier (node scope, needs node-notifier) and claims mail-store (mail-store.accounts/search/read/send); checks/mailstore refuses any other claimant of mail-store. New module mesh-mail-notifier (runs-as its own account, consumes mesh-mail's added events, claims mail-notifier): shows each new inbox mail once per machine through node-notifier.send; quiet for read mail, own address, other folders and first sync; more than three in a minute folded; failed notices retried; emits shown.
- Issue 797 (ADR 0380 §8): messenger's operator-channel gains tell: one plain message, every channel once, never held or escalated, only Details, its own cap.
Needs mesh-controller's `needs` field (issue 802), hence after: above.
Reviewed locally: rounds 1 to 3 changes, round 4 approved at c2cd2e1. merge-check.sh green with MESH_GATE built from mesh-controller feat/mail-seats (health count 62). Follow-ups: 839, 841.
Declares mail-store and mail-webclient (held once for the mesh) and mail-notifier
(held once per machine, needing node-notifier) per ADR 0378 as amended by ADR 0379.
Claims mail-store and serves its four verbs through the same handlers as the
existing mail_* tools. Moves the event shape (EventKey, Changes) into its own
file, mailevent.go, so mesh-mail-notifier (issue 800 part B) can carry a
byte-identical copy. Adds checks/mailstore, refusing any manifest but mesh-mail's
own that claims mail-store (ADR 0378 §3), wired into merge-check.sh.
ADR 0378 §9 as amended by ADR 0379: a module of its own, built from mesh-mail's
event shape, runs as its own account to hear mesh-mail's restricted MAIL stream
(ADR 0376 §2), shows each new inbox mail through node-notifier.send at most
once, folds more than three from one account into one notice, and emits its
own shown event.
ADR 0380 §8: the operator channel's notify is shaped for conditions (a key that
stays open, escalation, a plain rule that rewrites a subject), so a module has
no way to say a plain notice such as new mail. tell sends a headline and one or
two lines at once to every channel, bypassing routing, the burst window and the
walk hold; it offers Details like any message, is kept in the history, but its
record is marked cleared at once so it never stays open. Its cap (10 a channel
an hour) is its own, apart from notify's and the conditions'.
Review round 1 of mesh-catalog found sentLastHour counting tells
against CapPerHour (ADR 0380 §8 says tells keep their own cap, never
shared), and the drop log firing on every drop instead of once an
hour per channel as the comment already said.
Flush now sorts accounts instead of walking a map, so notice order is
stable. A failed node-notifier.send keeps its mail pending and retries
at most once a minute, without holding up other accounts' notices, and
the failure is kept in the Store for a new health tool
(mail_notifier_health) that is unhealthy past ten minutes of failure.
The burst rule now follows the lead's reading of ADR 0378 S9: within an
account's sliding minute, the first three qualifying mails are shown
one by one and the rest are folded into one notice at the window's
end; there is no separate quiet-gap timer. The dedupe key is the
account and message id, falling back to folder/uidvalidity/uid only
when no message id is given, so a UIDVALIDITY reset cannot suppress a
new mail, and a redelivered event already buffered is never recounted.
status now lists every granted account, not only those with a notice,
and caches mail-store.accounts for a minute.
ADR 0227 rule 8 / ADR 0240 rule 2 refuse a module with no health check of
another kind beside a tool check. mesh-mail-notifier has one process
(notify); wiring mail_notifier_health as its manifest health, as the review
note's wording suggested (mirroring mesh-mail's watch/mail_health), trips
that rule because mesh-mail also has keep (kind unit) beside watch.
mail_notifier_health stays built, tested and callable; notify's manifest
health stays kind unit until the lead decides how a one-process module
gets this automatically.
A buffer was replaced, discarding whatever it still held unsent, once
Window had passed since its first mail — losing a failed send waiting
for its retry, or a folded mail waiting for its minute's end, if a new
mail arrived meanwhile. The window now slides on the gap since the
last mail, not on time elapsed since the first: a session's count
never resets, and its buffer is never replaced, while anything in it
is still unsent.
The fold notice now counts every mail of the account in that minute,
not only the overflow, and says "mail" for one and "mails" for more.
A dropped tell was kept in the same bounded send history (KeptSends)
that the conditions' and notify's cap counts sends from. A flood of
drops could push real, still-recent sends out of that bounded history,
undercounting sentLastHour and letting the conditions' cap stop
holding. A dropped tell is still said once an hour in the log and
named in Tell's own "dropped" answer; it is simply never recorded into
that shared history any more.
mesh/merge-gate head c2cd2e1eb15e merged into trunk 789b0a9474c8 — pass: builds mesh-mail, messenger, new: modules/mesh-mail-notifier → novox; no bus step;…
mesh/repo-check head c2cd2e1eb15e merged into trunk 789b0a9474c8 — pass: THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the ch…
A session that only reset after a quiet minute kept counting, and so folding, a steady
trickle of mail forever even with no burst (one mail every 50s). N is now the account's
qualifying mail arrived in the trailing 60 seconds, counted fresh on every arrival; a fold
holds only its own overflow and the notice names just that count, not the whole history.
2026-10-15 17:04 (new) → proposed (announced): novox/mesh-catalog#317's head announced
2026-10-15 17:05 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
2026-10-15 17:05 checked → rejected (refused): the gate failed or could not run, or the repository's own check failed
2026-10-15 17:54 rejected → proposed (recheck): its merge check read mesh-mail's seat needs with a controller that predates issue 802; mesh-controller #345, which understands it, is merged and delivered (plan-1792086262420440231 done)
2026-10-15 17:56 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
2026-10-15 17:56 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-15 18:04 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-15 18:04 published → held (hold): something holds it for a person: its group's composed check did not pass for the heads that merged, or it merged and no walk was opened for it
2026-10-15 19:08 held → delivering (release): the operator's word (2026-10-15 21:05): release. The group feat/mail-seats's composed check failed only on merge order (mesh-controller's check read mesh-host at the running commit; mesh-catalog's read manifests with the controller running before #345); each member passed both required checks at the head that merged, and #345 and #113 are delivered.
2026-10-15 19:10 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-catalog@c2cd2e1eb15e` — **delivered** since 2026-10-15T19:10:01Z
**Delivery plan** — builds mesh-mail, messenger, new: modules/mesh-mail-notifier → novox; no bus step
- tier 0: mesh-mail, messenger
- novox: receives mesh-mail, messenger
**Group** `feat/mail-seats`, in order: novox/mesh-controller@5cf8938f55b3 → novox/mesh-catalog@c2cd2e1eb15e → novox/mesh-host@c3b2fce0a29f
- novox/mesh-controller@a18c17d3cc5f before novox/mesh-catalog@c2cd2e1eb15e: declared
**Machines**
- mesh-mail on every machine running it: sent
- messenger on every machine running it: sent
**Transitions**
- 2026-10-15 17:04 (new) → proposed (announced): novox/mesh-catalog#317's head announced
- 2026-10-15 17:05 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
- 2026-10-15 17:05 checked → rejected (refused): the gate failed or could not run, or the repository's own check failed
- 2026-10-15 17:54 rejected → proposed (recheck): its merge check read mesh-mail's seat `needs` with a controller that predates issue 802; mesh-controller #345, which understands it, is merged and delivered (plan-1792086262420440231 done)
- 2026-10-15 17:56 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
- 2026-10-15 17:56 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-15 18:04 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-15 18:04 published → held (hold): something holds it for a person: its group's composed check did not pass for the heads that merged, or it merged and no walk was opened for it
- 2026-10-15 19:08 held → delivering (release): the operator's word (2026-10-15 21:05): release. The group feat/mail-seats's composed check failed only on merge order (mesh-controller's check read mesh-host at the running commit; mesh-catalog's read manifests with the controller running before #345); each member passed both required checks at the head that merged, and #345 and #113 are delivered.
- 2026-10-15 19:10 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 c2cd2e1e
Judged: head c2cd2e1eb15e merged into trunk 789b0a9474c8; read beside it: mesh-controller 0ab61d1be8c5, mesh-controller-main 0ab61d1be8c5, mesh-host 198fd34ec497, mesh-tools 6b3e15042fee
mesh/merge-gate: FAIL — a manifest the change touches fails the module check: modules/mesh-mail/module.json: this manifest says "needs", which is now called "own-secrets": json: unknown field "needs" (read without seats[2].needs) (modules: mesh-mail, messenger, new:modules/mesh-mail-notifier)
mesh/repo-check: FAIL — THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges; its merge-check.sh failed: files asking for a setting without saying whether it is trusted: 25
Delivery plan — builds mesh-mail, messenger, new: modules/mesh-mail-notifier → novox; no bus step
tier 0: mesh-mail, messenger
novox: receives mesh-mail, messenger
read by no module's build: checks/mailstore/go.mod, checks/mailstore/main.go, checks/mailstore/main_test.go, merge-check.sh, modules/mesh-mail/README.md, modules/mesh-mail/cmd/mesh-mail/manifest_test.go, modules/messenger/cmd/messenger/holder_test.go, modules/messenger/cmd/messenger/manifest_test.go
Run by the build seat on shanks as build-1792083883069520203 (builds --log build-1792083883069520203).
--- the gate: mesh-mail, messenger, new:modules/mesh-mail-notifier
modules/mesh-mail/module.json: this manifest says "needs", which is now called "own-secrets": json: unknown field "needs" (read without seats[2].needs)
note: mesh-mail-notifier claims the seat "mail-notifier", which no module declares and the mesh does not define among the manifests given; registration judges it against the whole catalogue, and passing the declaring module's manifest too judges it here
mesh-mail-notifier: ok, 2 tool(s), invokes seat:node-notifier.send, seat:mail-store.accounts, keeps state shown, ready: notify by unit every 30s
messenger: ok, 7 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, seat:issue-tracker.tracking, keeps state open, sent, asks, identities, walks; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 1
mesh-controller: 1 problem(s) in 3 manifest(s)
--- the same manifests on main
modules/mesh-mail-notifier/module.json: open modules/mesh-mail-notifier/module.json: no such file or directory
mesh-mail: ok, 6 tool(s), keeps state sends, ready: keep by unit every 30s; watch by its tool mail_health every 1m0s
messenger: ok, 7 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, seat:issue-tracker.tracking, keeps state open, sent, asks, identities, walks; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 1
mesh-controller: 1 problem(s) in 3 manifest(s)
--- THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges
--- its merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-catalog/checks/words 0.003s
words: 12 retired words and 70 daemons' lines, none in the 48729 strings of 746 files
ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.013s
agent-home: no archive and no file written into under the agent's home
ok git.novox.be/novox/mesh-catalog/checks/secrets 0.013s
secrets: no setting can replace a vault secret in a mergeable file (1 known, nested)
ok git.novox.be/novox/mesh-catalog/checks/paths 0.006s
paths: no module names another's state on its machine (3 known, listed to go)
mesh-controller: 2 problem(s) in 131 manifest(s)
modules/mesh-mail/module.json: this manifest says "needs", which is now called "own-secrets": json: unknown field "needs" (read without seats[2].needs)
mesh-mail-notifier claims the seat "mail-notifier", which no module declares and the mesh does not define
adwaita: ok, 4 tool(s)
artifact-store-tools: ok, 4 tool(s), invokes seat:mesh-controller.artifacts, seat:mesh-controller.collect, mesh-catalog.catalog_modules, mesh-catalog.catalog_module
asus-zephyrus-g14: ok, 11 tool(s); WARNING: asusd, supergfxd, upower stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
audit-logger: ok, keeps trail (valuable), spool (valuable)
avahi: ok, 4 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
baserow: ok, keeps data (valuable), ready: server by its image's own check every 30s; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
betterbird: ok, 17 tool(s), invokes seat:mesh-controller.settings, seat:mesh-controller.nodes, seat:mesh-controller.node, betterbird.betterbird_derive
blueman: ok, 3 tool(s)
bluetooth: ok, 9 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
build-agent: ok, keeps workspace (cache), judge-cache (cache), ready: server by exec every 10s
ca-trust: ok; WARNING: trust stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
claude-code: ok, 48 tool(s), keeps state servers, holdings, config, proposals, questions, memory, reads claude-licence-manager.bindings, keeps agent-home (valuable); WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
claude-licence-manager: ok, keeps state bindings, reads claude-code.holdings; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
clipmenu: ok, 3 tool(s)
confluence: ok
cups: ok, 7 tool(s); WARNING: socket, scheduler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
dbus: ok, 5 tool(s); WARNING: system-bus stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
de-spiegel: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
desk-channel: ok, 1 tool(s), invokes seat:node-notifier.send, keeps state shown; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
dev-tools: ok
disk-load: ok, 5 tool(s)
distribution: ok, keeps registry (rebuildable); WARNING: store stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
dmenu: ok, 2 tool(s)
dnsmasq: ok, 3 tool(s), ready: service by unit every 30s; watch by its tool dnsmasq_health every 20s
docker: ok, 22 tool(s), invokes seat:mesh-controller.images; WARNING: socket, runtime, prune stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
docker-compose: ok, 9 tool(s)
dunst: ok, 6 tool(s)
fail2ban: ok, 2 tool(s), ready: watch by its tool fail2ban_health every 1m0s; run by unit every 30s
feh: ok, 2 tool(s)
flatpak: ok, 11 tool(s)
fonts: ok, 6 tool(s)
forticlient: ok, 3 tool(s), ready: split-dns by unit every 30s; WARNING: scheduler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
gitea: ok, keeps data (valuable), ready: server by http /api/healthz on web expecting 200 every 30s
gitlab: ok
gnome-keyring: ok, 4 tool(s)
grafana: ok, keeps data (valuable), ready: server by http / on web every 30s; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
hello-web: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
home-assistant: ok, keeps config (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
hostname: ok; WARNING: name 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)
i3: ok, 10 tool(s)
i3status-rust: ok, 4 tool(s)
icecast: ok, keeps logs (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
influxdb: ok, keeps data (valuable), config (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
invoicing: ok; WARNING: app, api stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
jira: ok
kernel: ok, 1 tool(s), ready: apply by unit every 30s
keycloak: ok; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
lab: ok, keeps work (cache); WARNING: runtime-env 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)
lemurs: ok, 2 tool(s); WARNING: service stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
letta: ok; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
local-model-consumer: ok
localization: ok, 4 tool(s)
logrotate: ok, 7 tool(s); WARNING: timer stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
mailu: ok, 11 tool(s), keeps mail (valuable), dkim (valuable), data (valuable), dav (valuable), webmail (valuable), queue (valuable), filter (rebuildable), certs (rebuildable), automx (rebuildable), fetchmail (rebuildable), clamav (cache), redis (cache), ready: resolver by its image's own check every 30s; admin by its image's own check every 30s; imap by its image's own check every 30s; smtp by its tool mailu_health every 1m0s; antispam by its image's own check every 30s; webmail by its image's own check every 30s; webdav by its image's own check every 30s; fetchmail by its image's own check every 30s; front by exec every 1m0s; WARNING: config-env 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: redis, antivirus, automx stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
marrytts: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
matrix: ok, keeps db (valuable), ready: element by its image's own check every 30s; WARNING: element-conf 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: homeserver stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
memory-pressure: ok, 6 tool(s); WARNING: oomd stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
mesh-catalog: ok
mesh-cli: ok
mesh-delivery: ok, 1 tool(s), invokes seat:mesh-controller.delivery-plan, seat:mesh-controller.delivery-order, seat:mesh-controller.delivery-check, seat:mesh-controller.deliver, seat:mesh-controller.delivery-stop, seat:mesh-controller.delivery-walks, seat:mesh-controller.forget-checks, gitea.gitea_note_append, gitea.gitea_delivery_view, gitea.gitea_commit_status, gitea.gitea_commit_statuses, gitea.gitea_contains, gitea.gitea_open_pulls, gitea.gitea_merge_pull_request, gitea.gitea_add_comment, gitea.gitea_api, keeps state deliveries, groups
mesh-issues: ok, invokes claude-code.claude_code_judge, seat:mesh-delivery.checks, seat:operator-channel.notify, gitea.gitea_pull_reviews, records.records_status, records.records_list, records.records_read, mesh-knowledge.knowledge_highest, keeps state issues, counters, grooming, reservations, keeps log changes (1024 MiB)
mesh-knowledge: ok, 2 tool(s), invokes seat:issue-tracker.reserve, claude-code.claude_code_judge, claude-code.claude_code_judged, records.records_status, records.records_list, records.records_read, seat:operator-channel.notify, ready: keep by unit every 30s; watch by its tool knowledge_health every 1m0s
mesh-mail-notifier: ok, 2 tool(s), invokes seat:node-notifier.send, seat:mail-store.accounts, keeps state shown, ready: notify by unit every 30s
mesh-reads: ok
mesh-vault: ok, keeps state (valuable), ledger (valuable), root (valuable)
mesh-watcher: ok, 4 tool(s), invokes mesh-watcher.watcher_ping, seat:mesh-controller.seats; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
messenger: ok, 7 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, seat:issue-tracker.tracking, keeps state open, sent, asks, identities, walks; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
minio: ok, keeps data (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
model-usage: ok, keeps state (cache), spool (valuable)
mongodb: ok, keeps data (valuable), dumps (rebuildable), ready: server by tcp on database every 30s
mosquitto: ok, keeps data (rebuildable), ready: server by tcp on mqtt every 30s
mounts: ok, 3 tool(s), invokes seat:mesh-controller.data, keeps state shares, reads nfs-server.exports, ready: apply by unit every 30s; watch by its tool mounts_health every 1m0s; WARNING: config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
mssql: ok, keeps data (valuable), dumps (rebuildable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
n8n: ok, keeps data (valuable), cache (cache), ready: server by http /healthz/readiness on web expecting 200 every 30s; WARNING: cache-server, browser stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
nats: ok, 9 tool(s), keeps jetstream (valuable), snapshots (rebuildable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
netcheck: ok, 5 tool(s)
networkmanager: ok
nextcloud: ok, keeps html (valuable), ready: server by http /status.php on web expecting 200 every 30s
nextcloud-client: ok, 4 tool(s)
nfs-server: ok, 1 tool(s), invokes seat:mesh-controller.seats, seat:mesh-controller.data, keeps state exports, reads mounts.shares, ready: server by unit every 30s; exports by its tool nfs_health every 1m0s; WARNING: config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
nftables: ok, 1 tool(s); WARNING: load stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
nm-applet: ok, 3 tool(s)
node-env: ok
nodered: ok, keeps data (valuable), ready: server by its image's own check every 30s; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
ollama: ok, keeps models (rebuildable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
only-office: ok, keeps data (rebuildable), lib (rebuildable), db (rebuildable), fonts (rebuildable), logs (cache), rabbitmq (cache), redis (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
openai-consumer: ok
openrazer: ok, 3 tool(s)
pacman: ok, 15 tool(s); WARNING: mirror-refresh, cache-cleaning stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
photos-eef: ok; WARNING: client stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
photos-filip: ok; WARNING: client stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
picom: ok, 4 tool(s); WARNING: configuration 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)
polychromatic: ok, 3 tool(s)
postgres: ok, keeps store (valuable), dumps (rebuildable), ready: server by tcp on database every 30s
power: ok, 5 tool(s), keeps state draw, ready: draw by unit every 30s; WARNING: logind-power 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: after-boot, before-shutdown stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
powerlevel10k: ok
records: ok, 6 tool(s), keeps checkout (rebuildable)
redis: ok, keeps data (cache), ready: server by tcp on cache every 30s
restic: ok, 3 tool(s), keeps repository (rebuildable), state (cache), ready: night by its tool backup_health every 1m0s; measure by unit every 30s
rofi: ok, 3 tool(s)
route-adapter: ok; WARNING: config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
route-proxy: ok, keeps acme (rebuildable), ca (cache), ready: server by tcp on http every 10s
screen-lock: ok, 3 tool(s)
searxng: ok, keeps valkey (cache); WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: cache, server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
sensors: ok, 6 tool(s), ready: drives by unit every 30s; watch by its tool sensors_health every 1m0s
showcase: ok; WARNING: server, tools stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
slack: ok, 4 tool(s)
snapd: ok, 10 tool(s)
ssh-client: ok, 8 tool(s), keeps ssh (valuable)
sshd: ok; WARNING: run stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
step-ca: ok, keeps home (valuable), ready: server by its image's own check every 30s
sudo: ok, 4 tool(s)
supabase: ok, keeps db (valuable), dumps (rebuildable), storage (valuable), functions (valuable), db-config (rebuildable), ready: db by its image's own check every 30s; kong by its image's own check every 30s; meta by its image's own check every 30s; studio by its image's own check every 30s; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: vector, analytics, auth, rest, realtime, imgproxy, storage-api, edge-functions, pooler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
systemd: ok
systemd-networkd: ok
systemd-resolved: ok, ready: service by unit every 30s; guard by unit every 30s
telegram: ok, 1 tool(s), keeps state offset, messages
time-sync: ok, 3 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
triggerhappy: ok, 4 tool(s); WARNING: service stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
umami: ok, ready: server by http /api/share/mesh-health on web expecting 404 every 30s
unifi: ok, keeps data (valuable); WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
website: ok, ready: server by http / on web every 30s
xclip: ok, 4 tool(s)
xdg: ok, 5 tool(s); WARNING: user-dirs 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)
xorg: ok, 9 tool(s)
xterm: ok, 2 tool(s)
zfs: ok, 15 tool(s), ready: watch by its tool zfs_health every 1m0s; events by unit every 30s; WARNING: scrub-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
zsh: ok, 1 tool(s); WARNING: tools-conf 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)
zsh-autosuggestions: ok
zsh-syntax-highlighting: ok
long-running resources without health: 62
files asking for a setting without saying whether it is trusted: 25
**Merge check** at `c2cd2e1e`
Judged: head `c2cd2e1eb15e` merged into trunk `789b0a9474c8`; read beside it: mesh-controller `0ab61d1be8c5`, mesh-controller-main `0ab61d1be8c5`, mesh-host `198fd34ec497`, mesh-tools `6b3e15042fee`
- `mesh/merge-gate`: **FAIL** — a manifest the change touches fails the module check: modules/mesh-mail/module.json: this manifest says "needs", which is now called "own-secrets": json: unknown field "needs" (read without seats[2].needs) (modules: mesh-mail, messenger, new:modules/mesh-mail-notifier)
- `mesh/repo-check`: **FAIL** — THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges; its merge-check.sh failed: files asking for a setting without saying whether it is trusted: 25
**Delivery plan** — builds mesh-mail, messenger, new: modules/mesh-mail-notifier → novox; no bus step
- tier 0: mesh-mail, messenger
- novox: receives mesh-mail, messenger
- read by no module's build: checks/mailstore/go.mod, checks/mailstore/main.go, checks/mailstore/main_test.go, merge-check.sh, modules/mesh-mail/README.md, modules/mesh-mail/cmd/mesh-mail/manifest_test.go, modules/messenger/cmd/messenger/holder_test.go, modules/messenger/cmd/messenger/manifest_test.go
Run by the build seat on shanks as `build-1792083883069520203` (`builds --log build-1792083883069520203`).
```
--- the gate: mesh-mail, messenger, new:modules/mesh-mail-notifier
modules/mesh-mail/module.json: this manifest says "needs", which is now called "own-secrets": json: unknown field "needs" (read without seats[2].needs)
note: mesh-mail-notifier claims the seat "mail-notifier", which no module declares and the mesh does not define among the manifests given; registration judges it against the whole catalogue, and passing the declaring module's manifest too judges it here
mesh-mail-notifier: ok, 2 tool(s), invokes seat:node-notifier.send, seat:mail-store.accounts, keeps state shown, ready: notify by unit every 30s
messenger: ok, 7 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, seat:issue-tracker.tracking, keeps state open, sent, asks, identities, walks; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 1
mesh-controller: 1 problem(s) in 3 manifest(s)
--- the same manifests on main
modules/mesh-mail-notifier/module.json: open modules/mesh-mail-notifier/module.json: no such file or directory
mesh-mail: ok, 6 tool(s), keeps state sends, ready: keep by unit every 30s; watch by its tool mail_health every 1m0s
messenger: ok, 7 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, seat:issue-tracker.tracking, keeps state open, sent, asks, identities, walks; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 1
mesh-controller: 1 problem(s) in 3 manifest(s)
--- THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges
--- its merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-catalog/checks/words 0.003s
words: 12 retired words and 70 daemons' lines, none in the 48729 strings of 746 files
ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.013s
agent-home: no archive and no file written into under the agent's home
ok git.novox.be/novox/mesh-catalog/checks/secrets 0.013s
secrets: no setting can replace a vault secret in a mergeable file (1 known, nested)
ok git.novox.be/novox/mesh-catalog/checks/paths 0.006s
paths: no module names another's state on its machine (3 known, listed to go)
mesh-controller: 2 problem(s) in 131 manifest(s)
modules/mesh-mail/module.json: this manifest says "needs", which is now called "own-secrets": json: unknown field "needs" (read without seats[2].needs)
mesh-mail-notifier claims the seat "mail-notifier", which no module declares and the mesh does not define
adwaita: ok, 4 tool(s)
artifact-store-tools: ok, 4 tool(s), invokes seat:mesh-controller.artifacts, seat:mesh-controller.collect, mesh-catalog.catalog_modules, mesh-catalog.catalog_module
asus-zephyrus-g14: ok, 11 tool(s); WARNING: asusd, supergfxd, upower stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
audit-logger: ok, keeps trail (valuable), spool (valuable)
avahi: ok, 4 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
baserow: ok, keeps data (valuable), ready: server by its image's own check every 30s; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
betterbird: ok, 17 tool(s), invokes seat:mesh-controller.settings, seat:mesh-controller.nodes, seat:mesh-controller.node, betterbird.betterbird_derive
blueman: ok, 3 tool(s)
bluetooth: ok, 9 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
build-agent: ok, keeps workspace (cache), judge-cache (cache), ready: server by exec every 10s
ca-trust: ok; WARNING: trust stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
claude-code: ok, 48 tool(s), keeps state servers, holdings, config, proposals, questions, memory, reads claude-licence-manager.bindings, keeps agent-home (valuable); WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
claude-licence-manager: ok, keeps state bindings, reads claude-code.holdings; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
clipmenu: ok, 3 tool(s)
confluence: ok
cups: ok, 7 tool(s); WARNING: socket, scheduler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
dbus: ok, 5 tool(s); WARNING: system-bus stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
de-spiegel: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
desk-channel: ok, 1 tool(s), invokes seat:node-notifier.send, keeps state shown; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
dev-tools: ok
disk-load: ok, 5 tool(s)
distribution: ok, keeps registry (rebuildable); WARNING: store stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
dmenu: ok, 2 tool(s)
dnsmasq: ok, 3 tool(s), ready: service by unit every 30s; watch by its tool dnsmasq_health every 20s
docker: ok, 22 tool(s), invokes seat:mesh-controller.images; WARNING: socket, runtime, prune stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
docker-compose: ok, 9 tool(s)
dunst: ok, 6 tool(s)
fail2ban: ok, 2 tool(s), ready: watch by its tool fail2ban_health every 1m0s; run by unit every 30s
feh: ok, 2 tool(s)
flatpak: ok, 11 tool(s)
fonts: ok, 6 tool(s)
forticlient: ok, 3 tool(s), ready: split-dns by unit every 30s; WARNING: scheduler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
gitea: ok, keeps data (valuable), ready: server by http /api/healthz on web expecting 200 every 30s
gitlab: ok
gnome-keyring: ok, 4 tool(s)
grafana: ok, keeps data (valuable), ready: server by http / on web every 30s; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
hello-web: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
home-assistant: ok, keeps config (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
hostname: ok; WARNING: name 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)
i3: ok, 10 tool(s)
i3status-rust: ok, 4 tool(s)
icecast: ok, keeps logs (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
influxdb: ok, keeps data (valuable), config (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
invoicing: ok; WARNING: app, api stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
jira: ok
kernel: ok, 1 tool(s), ready: apply by unit every 30s
keycloak: ok; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
lab: ok, keeps work (cache); WARNING: runtime-env 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)
lemurs: ok, 2 tool(s); WARNING: service stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
letta: ok; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
local-model-consumer: ok
localization: ok, 4 tool(s)
logrotate: ok, 7 tool(s); WARNING: timer stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
mailu: ok, 11 tool(s), keeps mail (valuable), dkim (valuable), data (valuable), dav (valuable), webmail (valuable), queue (valuable), filter (rebuildable), certs (rebuildable), automx (rebuildable), fetchmail (rebuildable), clamav (cache), redis (cache), ready: resolver by its image's own check every 30s; admin by its image's own check every 30s; imap by its image's own check every 30s; smtp by its tool mailu_health every 1m0s; antispam by its image's own check every 30s; webmail by its image's own check every 30s; webdav by its image's own check every 30s; fetchmail by its image's own check every 30s; front by exec every 1m0s; WARNING: config-env 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: redis, antivirus, automx stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
marrytts: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
matrix: ok, keeps db (valuable), ready: element by its image's own check every 30s; WARNING: element-conf 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: homeserver stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
memory-pressure: ok, 6 tool(s); WARNING: oomd stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
mesh-catalog: ok
mesh-cli: ok
mesh-delivery: ok, 1 tool(s), invokes seat:mesh-controller.delivery-plan, seat:mesh-controller.delivery-order, seat:mesh-controller.delivery-check, seat:mesh-controller.deliver, seat:mesh-controller.delivery-stop, seat:mesh-controller.delivery-walks, seat:mesh-controller.forget-checks, gitea.gitea_note_append, gitea.gitea_delivery_view, gitea.gitea_commit_status, gitea.gitea_commit_statuses, gitea.gitea_contains, gitea.gitea_open_pulls, gitea.gitea_merge_pull_request, gitea.gitea_add_comment, gitea.gitea_api, keeps state deliveries, groups
mesh-issues: ok, invokes claude-code.claude_code_judge, seat:mesh-delivery.checks, seat:operator-channel.notify, gitea.gitea_pull_reviews, records.records_status, records.records_list, records.records_read, mesh-knowledge.knowledge_highest, keeps state issues, counters, grooming, reservations, keeps log changes (1024 MiB)
mesh-knowledge: ok, 2 tool(s), invokes seat:issue-tracker.reserve, claude-code.claude_code_judge, claude-code.claude_code_judged, records.records_status, records.records_list, records.records_read, seat:operator-channel.notify, ready: keep by unit every 30s; watch by its tool knowledge_health every 1m0s
mesh-mail-notifier: ok, 2 tool(s), invokes seat:node-notifier.send, seat:mail-store.accounts, keeps state shown, ready: notify by unit every 30s
mesh-reads: ok
mesh-vault: ok, keeps state (valuable), ledger (valuable), root (valuable)
mesh-watcher: ok, 4 tool(s), invokes mesh-watcher.watcher_ping, seat:mesh-controller.seats; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
messenger: ok, 7 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, seat:issue-tracker.tracking, keeps state open, sent, asks, identities, walks; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
minio: ok, keeps data (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
model-usage: ok, keeps state (cache), spool (valuable)
mongodb: ok, keeps data (valuable), dumps (rebuildable), ready: server by tcp on database every 30s
mosquitto: ok, keeps data (rebuildable), ready: server by tcp on mqtt every 30s
mounts: ok, 3 tool(s), invokes seat:mesh-controller.data, keeps state shares, reads nfs-server.exports, ready: apply by unit every 30s; watch by its tool mounts_health every 1m0s; WARNING: config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
mssql: ok, keeps data (valuable), dumps (rebuildable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
n8n: ok, keeps data (valuable), cache (cache), ready: server by http /healthz/readiness on web expecting 200 every 30s; WARNING: cache-server, browser stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
nats: ok, 9 tool(s), keeps jetstream (valuable), snapshots (rebuildable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
netcheck: ok, 5 tool(s)
networkmanager: ok
nextcloud: ok, keeps html (valuable), ready: server by http /status.php on web expecting 200 every 30s
nextcloud-client: ok, 4 tool(s)
nfs-server: ok, 1 tool(s), invokes seat:mesh-controller.seats, seat:mesh-controller.data, keeps state exports, reads mounts.shares, ready: server by unit every 30s; exports by its tool nfs_health every 1m0s; WARNING: config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
nftables: ok, 1 tool(s); WARNING: load stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
nm-applet: ok, 3 tool(s)
node-env: ok
nodered: ok, keeps data (valuable), ready: server by its image's own check every 30s; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
ollama: ok, keeps models (rebuildable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
only-office: ok, keeps data (rebuildable), lib (rebuildable), db (rebuildable), fonts (rebuildable), logs (cache), rabbitmq (cache), redis (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
openai-consumer: ok
openrazer: ok, 3 tool(s)
pacman: ok, 15 tool(s); WARNING: mirror-refresh, cache-cleaning stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
photos-eef: ok; WARNING: client stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
photos-filip: ok; WARNING: client stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
picom: ok, 4 tool(s); WARNING: configuration 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)
polychromatic: ok, 3 tool(s)
postgres: ok, keeps store (valuable), dumps (rebuildable), ready: server by tcp on database every 30s
power: ok, 5 tool(s), keeps state draw, ready: draw by unit every 30s; WARNING: logind-power 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: after-boot, before-shutdown stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
powerlevel10k: ok
records: ok, 6 tool(s), keeps checkout (rebuildable)
redis: ok, keeps data (cache), ready: server by tcp on cache every 30s
restic: ok, 3 tool(s), keeps repository (rebuildable), state (cache), ready: night by its tool backup_health every 1m0s; measure by unit every 30s
rofi: ok, 3 tool(s)
route-adapter: ok; WARNING: config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
route-proxy: ok, keeps acme (rebuildable), ca (cache), ready: server by tcp on http every 10s
screen-lock: ok, 3 tool(s)
searxng: ok, keeps valkey (cache); WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: cache, server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
sensors: ok, 6 tool(s), ready: drives by unit every 30s; watch by its tool sensors_health every 1m0s
showcase: ok; WARNING: server, tools stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
slack: ok, 4 tool(s)
snapd: ok, 10 tool(s)
ssh-client: ok, 8 tool(s), keeps ssh (valuable)
sshd: ok; WARNING: run stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
step-ca: ok, keeps home (valuable), ready: server by its image's own check every 30s
sudo: ok, 4 tool(s)
supabase: ok, keeps db (valuable), dumps (rebuildable), storage (valuable), functions (valuable), db-config (rebuildable), ready: db by its image's own check every 30s; kong by its image's own check every 30s; meta by its image's own check every 30s; studio by its image's own check every 30s; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: vector, analytics, auth, rest, realtime, imgproxy, storage-api, edge-functions, pooler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
systemd: ok
systemd-networkd: ok
systemd-resolved: ok, ready: service by unit every 30s; guard by unit every 30s
telegram: ok, 1 tool(s), keeps state offset, messages
time-sync: ok, 3 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
triggerhappy: ok, 4 tool(s); WARNING: service stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
umami: ok, ready: server by http /api/share/mesh-health on web expecting 404 every 30s
unifi: ok, keeps data (valuable); WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
website: ok, ready: server by http / on web every 30s
xclip: ok, 4 tool(s)
xdg: ok, 5 tool(s); WARNING: user-dirs 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)
xorg: ok, 9 tool(s)
xterm: ok, 2 tool(s)
zfs: ok, 15 tool(s), ready: watch by its tool zfs_health every 1m0s; events by unit every 30s; WARNING: scrub-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
zsh: ok, 1 tool(s); WARNING: tools-conf 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)
zsh-autosuggestions: ok
zsh-syntax-highlighting: ok
long-running resources without health: 62
files asking for a setting without saying whether it is trusted: 25
```
Merge check at c2cd2e1e
Judged: head c2cd2e1eb15e merged into trunk 789b0a9474c8; read beside it: mesh-controller 7543f64911c5, mesh-controller-main 7543f64911c5, mesh-host 198fd34ec497, mesh-tools 6b3e15042fee
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-mail, messenger, new:modules/mesh-mail-notifier)
mesh/repo-check: PASS — THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges; its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
Delivery plan — builds mesh-mail, messenger, new: modules/mesh-mail-notifier → novox; no bus step
tier 0: mesh-mail, messenger
novox: receives mesh-mail, messenger
read by no module's build: checks/mailstore/go.mod, checks/mailstore/main.go, checks/mailstore/main_test.go, merge-check.sh, modules/mesh-mail/README.md, modules/mesh-mail/cmd/mesh-mail/manifest_test.go, modules/messenger/cmd/messenger/holder_test.go, modules/messenger/cmd/messenger/manifest_test.go
Run by the build seat on ace as build-1792086859883146927 (builds --log build-1792086859883146927).
--- the gate: mesh-mail, messenger, new:modules/mesh-mail-notifier
mesh-mail: ok, 10 tool(s), keeps state sends, ready: keep by unit every 30s; watch by its tool mail_health every 1m0s
mesh-mail-notifier: ok, 2 tool(s), invokes seat:node-notifier.send, seat:mail-store.accounts, keeps state shown, ready: notify by unit every 30s
messenger: ok, 7 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, seat:issue-tracker.tracking, keeps state open, sent, asks, identities, walks; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 1
3 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 3 module(s) changed against 4 machine(s), as the snapshot of 2026-10-15T17:48:28Z 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-15T17:48:28Z
modules the change moves:
- mesh-mail (changed)
- mesh-mail-notifier (added)
- 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): mesh-mail, messenger
notes:
- mesh-mail-notifier could not be tried on a machine: mesh-mail-notifier on f35 has no bus credential: nothing was issued for f35.mesh-mail-notifier, and a push would seal a placeholder its process cannot read (novox/hq issue 203). `module issue mesh-mail-notifier --node f35`, then push again
- checks/mailstore/go.mod, checks/mailstore/main.go, checks/mailstore/main_test.go, merge-check.sh, modules/mesh-mail/README.md, modules/mesh-mail/cmd/mesh-mail/manifest_test.go, modules/messenger/cmd/messenger/holder_test.go and modules/messenger/cmd/messenger/manifest_test.go read by no module's build, and rebuild nothing (issue 280)
--- THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges
--- its merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-catalog/checks/words 0.005s
words: 12 retired words and 70 daemons' lines, none in the 48729 strings of 746 files
ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.011s
agent-home: no archive and no file written into under the agent's home
ok git.novox.be/novox/mesh-catalog/checks/secrets 0.011s
secrets: no setting can replace a vault secret in a mergeable file (1 known, nested)
ok git.novox.be/novox/mesh-catalog/checks/paths 0.005s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 62, as kept
ok git.novox.be/novox/mesh-catalog/checks/deps 0.199s
testing modules/mesh-mail
ok mesh-mail/cmd/mesh-mail 3.031s
testing modules/mesh-mail-notifier
ok mesh-mail-notifier/cmd/mesh-mail-notifier 1.011s
testing modules/messenger
ok messenger/cmd/messenger 2.017s
--- its merge-check-typescript.sh (typescript toolchain)
**Merge check** at `c2cd2e1e`
Judged: head `c2cd2e1eb15e` merged into trunk `789b0a9474c8`; read beside it: mesh-controller `7543f64911c5`, mesh-controller-main `7543f64911c5`, mesh-host `198fd34ec497`, mesh-tools `6b3e15042fee`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-mail, messenger, new:modules/mesh-mail-notifier)
- `mesh/repo-check`: **PASS** — THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges; its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
**Delivery plan** — builds mesh-mail, messenger, new: modules/mesh-mail-notifier → novox; no bus step
- tier 0: mesh-mail, messenger
- novox: receives mesh-mail, messenger
- read by no module's build: checks/mailstore/go.mod, checks/mailstore/main.go, checks/mailstore/main_test.go, merge-check.sh, modules/mesh-mail/README.md, modules/mesh-mail/cmd/mesh-mail/manifest_test.go, modules/messenger/cmd/messenger/holder_test.go, modules/messenger/cmd/messenger/manifest_test.go
Run by the build seat on ace as `build-1792086859883146927` (`builds --log build-1792086859883146927`).
```
--- the gate: mesh-mail, messenger, new:modules/mesh-mail-notifier
mesh-mail: ok, 10 tool(s), keeps state sends, ready: keep by unit every 30s; watch by its tool mail_health every 1m0s
mesh-mail-notifier: ok, 2 tool(s), invokes seat:node-notifier.send, seat:mail-store.accounts, keeps state shown, ready: notify by unit every 30s
messenger: ok, 7 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, seat:issue-tracker.tracking, keeps state open, sent, asks, identities, walks; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 1
3 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 3 module(s) changed against 4 machine(s), as the snapshot of 2026-10-15T17:48:28Z 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-15T17:48:28Z
modules the change moves:
- mesh-mail (changed)
- mesh-mail-notifier (added)
- 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): mesh-mail, messenger
notes:
- mesh-mail-notifier could not be tried on a machine: mesh-mail-notifier on f35 has no bus credential: nothing was issued for f35.mesh-mail-notifier, and a push would seal a placeholder its process cannot read (novox/hq issue 203). `module issue mesh-mail-notifier --node f35`, then push again
- checks/mailstore/go.mod, checks/mailstore/main.go, checks/mailstore/main_test.go, merge-check.sh, modules/mesh-mail/README.md, modules/mesh-mail/cmd/mesh-mail/manifest_test.go, modules/messenger/cmd/messenger/holder_test.go and modules/messenger/cmd/messenger/manifest_test.go read by no module's build, and rebuild nothing (issue 280)
--- THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges
--- its merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-catalog/checks/words 0.005s
words: 12 retired words and 70 daemons' lines, none in the 48729 strings of 746 files
ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.011s
agent-home: no archive and no file written into under the agent's home
ok git.novox.be/novox/mesh-catalog/checks/secrets 0.011s
secrets: no setting can replace a vault secret in a mergeable file (1 known, nested)
ok git.novox.be/novox/mesh-catalog/checks/paths 0.005s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 62, as kept
ok git.novox.be/novox/mesh-catalog/checks/deps 0.199s
testing modules/mesh-mail
ok mesh-mail/cmd/mesh-mail 3.031s
testing modules/mesh-mail-notifier
ok mesh-mail-notifier/cmd/mesh-mail-notifier 1.011s
testing modules/messenger
ok messenger/cmd/messenger 2.017s
--- its merge-check-typescript.sh (typescript toolchain)
```
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.
Feature feat/mail-seats (playbook 07), one delivery group with novox/mesh-controller and novox/mesh-host.
after: novox/mesh-controller
Needs mesh-controller's
needsfield (issue 802), hence after: above.Reviewed locally: rounds 1 to 3 changes, round 4 approved at
c2cd2e1. merge-check.sh green with MESH_GATE built from mesh-controller feat/mail-seats (health count 62). Follow-ups: 839, 841.Delivery
novox/mesh-catalog@c2cd2e1eb15e— delivered since 2026-10-15T19:10:01ZDelivery plan — builds mesh-mail, messenger, new: modules/mesh-mail-notifier → novox; no bus step
Group
feat/mail-seats, in order: novox/mesh-controller@5cf8938f55 → novox/mesh-catalog@c2cd2e1eb1 → novox/mesh-host@c3b2fce0a2Machines
Transitions
needswith a controller that predates issue 802; mesh-controller #345, which understands it, is merged and delivered (plan-1792086262420440231 done)The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Merge check at
c2cd2e1eJudged: head
c2cd2e1eb15emerged into trunk789b0a9474c8; read beside it: mesh-controller0ab61d1be8c5, mesh-controller-main0ab61d1be8c5, mesh-host198fd34ec497, mesh-tools6b3e15042feemesh/merge-gate: FAIL — a manifest the change touches fails the module check: modules/mesh-mail/module.json: this manifest says "needs", which is now called "own-secrets": json: unknown field "needs" (read without seats[2].needs) (modules: mesh-mail, messenger, new:modules/mesh-mail-notifier)mesh/repo-check: FAIL — THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges; its merge-check.sh failed: files asking for a setting without saying whether it is trusted: 25Delivery plan — builds mesh-mail, messenger, new: modules/mesh-mail-notifier → novox; no bus step
Run by the build seat on shanks as
build-1792083883069520203(builds --log build-1792083883069520203).Merge check at
c2cd2e1eJudged: head
c2cd2e1eb15emerged into trunk789b0a9474c8; read beside it: mesh-controller7543f64911c5, mesh-controller-main7543f64911c5, mesh-host198fd34ec497, mesh-tools6b3e15042feemesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-mail, messenger, new:modules/mesh-mail-notifier)mesh/repo-check: PASS — THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges; its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)Delivery plan — builds mesh-mail, messenger, new: modules/mesh-mail-notifier → novox; no bus step
Run by the build seat on ace as
build-1792086859883146927(builds --log build-1792086859883146927).