Issue 320 and ADR 0253: a condition says itself to the operator in plain words
mesh/merge-gate pass: the change touches no module of the mesh's graph
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request

The operator could not read the mesh's notifications: they were the summary meant
for an agent, with ids, commits, keys and verbs, in UTC. The condition now carries
a headline, an explanation and a resolved line beside its summary.
This commit is contained in:
jochen
2026-10-08 13:28:50 +02:00
parent 73fa97efde
commit 7c49aa0ffc
4 changed files with 251 additions and 1 deletions
@@ -0,0 +1,78 @@
---
status: located
opened: 2026-10-08
located-in: [mesh-controller internal/conditions (the condition's words), mesh-controller cmd/mesh-controller (every producer of a condition), mesh-catalog modules/messenger (compose, the digest)]
fixed-by:
amended-design: 03-DESIGN/01-to-be/45-a-core-that-cannot-fail-silently.md
---
# 320. The operator could not read the mesh's notifications
## Symptom
On 2026-10-08 the operator said they could not read the mesh's desktop notifications. One, exactly as
it appeared on the laptop, with the plan id and the commit replaced here by placeholders:
> CLEARED after 26 min: the walk of novox/mesh-catalog `<commit>` has waited 56m0s for mesh-delivery's
> word to start: `mesh-delivery.show` for the delivery that landed as `<commit>` says why; `plans go
> <plan id> --why ...` starts it by hand
> about: plan `<plan id>` (waiting)
> since: 2026-10-08 10:40 UTC
> key: plan.`<plan id>`.waiting
> more: conditions show plan.`<plan id>`.waiting
What is wrong with it, as the operator listed it:
- It is a wall of text, five lines and some sixty words for one fact.
- It is full of identifiers: a plan id, a commit, a condition key and a verb's syntax.
- Its time is UTC, not the operator's.
- Its backticks are markdown, which a desktop popup shows literally.
- A clearance repeats the whole problem.
- It does not say in plain words what happened, whether the operator needs to act, or what to do.
The same shape held for every open condition on the mesh that day: a module unhealthy on the laptop
("… its unit `<name>.service` failed in the account's own service manager (exit-code)"), three failed
units on a workstation, a cause repaired by hand thirty-five times, five deliveries held past their bound,
each with `mesh-delivery.show <repository>@<commit>` in its line.
## Cause
**The condition had one line of words, and it served two readers.** To-be 45 §2 gave a condition one
`summary`, "one line in the mesh's words", and §5 made a message out of that summary with the key,
subject, kind, since-when and the verb that shows more. The summary was written for whoever looks closer
— an agent at the mesh MCP server, a person reading `conditions` — and rightly carried what they act on:
the plan, the commit, the verb. Nothing in the condition was written for the operator who reads a popup
between other work, so the channel showed the agent's line to the operator.
Issue 277 had already found the narrower half: a summary carried detail the content rule refuses, and the
controller now holds every summary to that rule. Identifiers, verbs and markup pass that rule — they are
not addresses, paths or secrets — so they reached the operator untouched.
**The message added its own detail.** The messenger's compose added `about:`, `since:` in UTC, `key:` and
`more:` lines to every message, and a digest added each key in brackets. A clearance was the whole
summary again behind "CLEARED after …".
## Fix
[ADR 0253](../../02-DECISIONS/0253-a-condition-says-itself-to-the-operator-in-plain-words-beside-its-summary.md):
every condition carries, beside its summary, a **headline**, an **explanation** and a **resolved line**
in plain words, made where the condition is made and held to a checked plain rule; every channel shows
those and says the time in the operator's zone; a clearance is one line.
- novox/mesh-controller: the condition's three new fields, the plain rule, a wording for every kind the
controller raises, the richer words at the producers that know more (a walk's modules, a unit's name, a
hand-act's cause, a delivery's repository), and a lint over every condition the suite raises.
- novox/mesh-catalog: the messenger shows the words, says since when in the operator's zone (the new
setting `time-zone`), says a clearance in one line, names nothing but titles in a digest, and lets a
module give the same words through `notify`.
## How it is checked
ADR 0253 §How it is checked: the plain rule's own test, a test per real notification above showing the
words before and after, the suite-wide lint, and the messenger's tests of the four messages as the desktop
shows them.
## Design
To-be 45 §2 gains the three fields, and §5's message is no longer the key, kind and verb but the
headline, the explanation and since when.