Issue 320 and ADR 0253: a condition says itself to the operator in plain words
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:
@@ -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.
|
||||
Reference in New Issue
Block a user