An ask reads at a glance on the phone: a headline, a summary and its points, the rest in a note (issues 383 and 639) #278

Merged
mesh-admin merged 3 commits from fix/383-an-ask-reads-at-a-glance into main 2026-10-13 19:02:21 +00:00
Contributor

Replaces #178 (issue 383), rebased on main and reshaped for issue 639.

Acceptance. The next decision ask the operator gets on Telegram is a bold headline saying what it changes for them, a two- or three-sentence summary and at most three points, the Approve/Decline buttons, and a collapsed note with who asked, the fingerprint and how to read the clauses; the ADR 0343 ask renders in 10 lines (it was ~30) and lists no clause. Answered, it is one line with the headline.

What.

  • messenger: an ask's message is the asker's headline (title) and explanation alone (body). Who asked and when with the expiry, what each answer does, where else it is answered, and the asker's Details go in the note (asks.Message.Note). Answered: "You chose Approve at 16:06 on Telegram · ", the told-line as its note, body not repeated. An explanation that fails asks.Glance is shown and logged, never refused. From #178: on a kind that proves who answers an ask's values are shown whole (asks.Ask.Whole), held to the secret rule alone (CheckSecret). The Details button of #178 is dropped: Details are now the note.
  • telegram: HTML; title bold, key lines monospace, note in <blockquote expandable> after a blank line; <>& escaped. Taps compared with whitespace runs taken as one; a message shown before is still compared by its old digest.
  • desk-channel: the note follows the body after a blank line.
  • mesh-knowledge: propose takes brief {headline, summary, points}; rule 30 brief requires it with needs-operator for records dated from 2026-10-13. The ask shows the brief, never the clauses; Details: record, proposer, review, fingerprint, "Read its N clauses with the knowledge base's get, number N". OperatorAsk.Form keeps an ask made before composed as it was, so its warrant still holds.
  • claude-code: an instructions proposal's explanation is one summary line (new optional summary, else the module's words), its text moved to the Details; a question's context is at most 300 characters and its recommendation one point. form keeps older proposals and questions composed as asked.

Design limits I chose (ADR 0345, proposed, needs the operator): summary ≤ 300 characters on one line, ≤ 3 points of ≤ 160; question context 1500 → 300 characters, why 300 → 120 bytes; more than three setting keys show two and the names of the rest.

Depends on mesh-sdk #25 (pinned at 9588871, pushed). Merge order: mesh-sdk #25, this, then mesh-controller's PR (the router must know Whole before the controller sends it, or the digests differ and the warrant is refused, loudly).

Tested. merge-check.sh with MESH_GATE (a controller built from the controller branch) and MESH_CHECK_MODULES=messenger,telegram,desk-channel,mesh-knowledge,claude-code: all green. New tests that fail on main: messenger TestAnAsksMessageIsItsSummaryWithTheRestInItsNote, TestAnAskThatIsAWallOfTextIsShownAndSaid; telegram TestTheADR0343AskFitsAGlance (≤ 12 lines, bold headline, collapsed note, no clause), TestALongNoteIsCutBeforeTheBody, TestATapOnAMessageShownBeforeIsStillTaken; mesh-knowledge TestADecisionAskReadsAtAGlance, TestABriefIsHeldToAGlance, the brief row of the rule table; claude-code TestAProposalIsAskedAtAGlanceAndAnOlderOneAsItWasAsked; desk-channel TestTheNoteFollowsTheBody. Existing tests were updated where the shape changed.

Fixes issue 639. Fixes issue 383 (with mesh-controller and hq).

Replaces #178 (issue 383), rebased on main and reshaped for issue 639. **Acceptance.** The next decision ask the operator gets on Telegram is a bold headline saying what it changes for them, a two- or three-sentence summary and at most three points, the Approve/Decline buttons, and a collapsed note with who asked, the fingerprint and how to read the clauses; the ADR 0343 ask renders in 10 lines (it was ~30) and lists no clause. Answered, it is one line with the headline. **What.** - **messenger**: an ask's message is the asker's headline (title) and explanation alone (body). Who asked and when with the expiry, what each answer does, where else it is answered, and the asker's Details go in the note (`asks.Message.Note`). Answered: "You chose Approve at 16:06 on Telegram · <headline>", the told-line as its note, body not repeated. An explanation that fails `asks.Glance` is shown and logged, never refused. From #178: on a kind that proves who answers an ask's values are shown whole (`asks.Ask.Whole`), held to the secret rule alone (`CheckSecret`). The Details button of #178 is dropped: Details are now the note. - **telegram**: HTML; title bold, key lines monospace, note in `<blockquote expandable>` after a blank line; `<>&` escaped. Taps compared with whitespace runs taken as one; a message shown before is still compared by its old digest. - **desk-channel**: the note follows the body after a blank line. - **mesh-knowledge**: `propose` takes `brief` {headline, summary, points}; rule 30 `brief` requires it with needs-operator for records dated from 2026-10-13. The ask shows the brief, never the clauses; Details: record, proposer, review, fingerprint, "Read its N clauses with the knowledge base's get, number N". `OperatorAsk.Form` keeps an ask made before composed as it was, so its warrant still holds. - **claude-code**: an instructions proposal's explanation is one summary line (new optional `summary`, else the module's words), its text moved to the Details; a question's context is at most 300 characters and its recommendation one point. `form` keeps older proposals and questions composed as asked. **Design limits I chose** (ADR 0345, proposed, needs the operator): summary ≤ 300 characters on one line, ≤ 3 points of ≤ 160; question context 1500 → 300 characters, why 300 → 120 bytes; more than three setting keys show two and the names of the rest. **Depends on** mesh-sdk #25 (pinned at 9588871, pushed). Merge order: mesh-sdk #25, this, then mesh-controller's PR (the router must know `Whole` before the controller sends it, or the digests differ and the warrant is refused, loudly). **Tested.** `merge-check.sh` with MESH_GATE (a controller built from the controller branch) and MESH_CHECK_MODULES=messenger,telegram,desk-channel,mesh-knowledge,claude-code: all green. New tests that fail on main: messenger `TestAnAsksMessageIsItsSummaryWithTheRestInItsNote`, `TestAnAskThatIsAWallOfTextIsShownAndSaid`; telegram `TestTheADR0343AskFitsAGlance` (≤ 12 lines, bold headline, collapsed note, no clause), `TestALongNoteIsCutBeforeTheBody`, `TestATapOnAMessageShownBeforeIsStillTaken`; mesh-knowledge `TestADecisionAskReadsAtAGlance`, `TestABriefIsHeldToAGlance`, the `brief` row of the rule table; claude-code `TestAProposalIsAskedAtAGlanceAndAnOlderOneAsItWasAsked`; desk-channel `TestTheNoteFollowsTheBody`. Existing tests were updated where the shape changed. Fixes issue 639. Fixes issue 383 (with mesh-controller and hq).
Author
Contributor

Delivery novox/mesh-catalog@f09daabec3a8 — delivered since 2026-10-13T19:17:50Z

Delivery plan — builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, novox, shanks; no bus step

  • tier 0: claude-code, desk-channel, mesh-knowledge, messenger, telegram
  • ace: receives claude-code
  • g14: receives claude-code
  • novox: receives claude-code, desk-channel, mesh-knowledge, messenger, telegram
  • shanks: receives claude-code
  • claude-code keeps data (ADR 0233): what it holds is backed up before it moves
  • grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before claude-code is judged on its first machine

Group fix/383-an-ask-reads-at-a-glance, in order: novox/mesh-catalog@f09daabec3 → novox/mesh-controller@deef9421a2

Machines

  • baserow on ace: passed — carried by plan-1791918149350551946
  • grafana on ace: passed — carried by plan-1791918149350551946
  • home-assistant on ace: passed — carried by plan-1791918149350551946
  • icecast on ace: passed — carried by plan-1791918149350551946
  • influxdb on ace: passed — carried by plan-1791918149350551946
  • letta on ace: passed — carried by plan-1791918149350551946
  • mosquitto on ace: passed — carried by plan-1791918149350551946
  • netcheck on ace: passed — carried by plan-1791918149350551946
  • nodered on ace: passed — carried by plan-1791918149350551946
  • redis on ace: passed — carried by plan-1791918149350551946
  • searxng on ace: passed — carried by plan-1791918149350551946
  • unifi on ace: passed — carried by plan-1791918149350551946
  • zsh on ace: passed — carried by plan-1791918149350551946
  • gitea on novox: passed — carried by plan-1791918149350551946
  • mesh-catalog on novox: passed — carried by plan-1791918149350551946
  • mesh-vault on novox: passed — carried by plan-1791918149350551946
  • nextcloud on novox: passed — carried by plan-1791918149350551946
  • umami on novox: passed — carried by plan-1791918149350551946
  • lab on shanks: passed — carried by plan-1791918149350551946
  • claude-code on ace: passed — healthy 1 times over 22s
  • claude-code on g14: passed — carried by release-1791918739498850280
  • claude-code on shanks: passed — carried by release-1791918739498850280
  • claude-code on novox: passed — carried by release-1791918739498850280
  • desk-channel on novox: passed — healthy 1 times over 1m6s
  • mesh-knowledge on novox: passed — judged with desk-channel: healthy 1 times over 1m6s
  • messenger on novox: passed — judged with desk-channel: healthy 1 times over 1m6s
  • telegram on novox: passed — judged with desk-channel: healthy 1 times over 1m6s
  • claude-code on the rest running it: sent
  • desk-channel on the rest running it: sent
  • mesh-knowledge on the rest running it: sent
  • messenger on the rest running it: sent
  • telegram on the rest running it: sent

Transitions

  • 2026-10-13 18:35 (new) → proposed (announced): novox/mesh-catalog#278's head announced
  • 2026-10-13 18:42 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
  • 2026-10-13 18:42 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
  • 2026-10-13 19:11 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
  • 2026-10-13 19:11 published → delivering (go): its walk started: let go by this owner in its group's order, by a person, or on the controller's own path — not a failed walk that carried a later commit for it, after which it waits for a walk of its own commit
  • 2026-10-13 19:17 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@f09daabec3a8` — **delivered** since 2026-10-13T19:17:50Z **Delivery plan** — builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, novox, shanks; no bus step - tier 0: claude-code, desk-channel, mesh-knowledge, messenger, telegram - ace: receives claude-code - g14: receives claude-code - novox: receives claude-code, desk-channel, mesh-knowledge, messenger, telegram - shanks: receives claude-code - claude-code keeps data (ADR 0233): what it holds is backed up before it moves - grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before claude-code is judged on its first machine **Group** `fix/383-an-ask-reads-at-a-glance`, in order: novox/mesh-catalog@f09daabec3a8 → novox/mesh-controller@deef9421a276 - novox/mesh-catalog@f09daabec3a8 before novox/mesh-controller@deef9421a276: declared, over built by, version skew - composed together: pass — every machine composes with the change as it did without (4 of 4 compose) **Machines** - baserow on ace: passed — carried by plan-1791918149350551946 - grafana on ace: passed — carried by plan-1791918149350551946 - home-assistant on ace: passed — carried by plan-1791918149350551946 - icecast on ace: passed — carried by plan-1791918149350551946 - influxdb on ace: passed — carried by plan-1791918149350551946 - letta on ace: passed — carried by plan-1791918149350551946 - mosquitto on ace: passed — carried by plan-1791918149350551946 - netcheck on ace: passed — carried by plan-1791918149350551946 - nodered on ace: passed — carried by plan-1791918149350551946 - redis on ace: passed — carried by plan-1791918149350551946 - searxng on ace: passed — carried by plan-1791918149350551946 - unifi on ace: passed — carried by plan-1791918149350551946 - zsh on ace: passed — carried by plan-1791918149350551946 - gitea on novox: passed — carried by plan-1791918149350551946 - mesh-catalog on novox: passed — carried by plan-1791918149350551946 - mesh-vault on novox: passed — carried by plan-1791918149350551946 - nextcloud on novox: passed — carried by plan-1791918149350551946 - umami on novox: passed — carried by plan-1791918149350551946 - lab on shanks: passed — carried by plan-1791918149350551946 - claude-code on ace: passed — healthy 1 times over 22s - claude-code on g14: passed — carried by release-1791918739498850280 - claude-code on shanks: passed — carried by release-1791918739498850280 - claude-code on novox: passed — carried by release-1791918739498850280 - desk-channel on novox: passed — healthy 1 times over 1m6s - mesh-knowledge on novox: passed — judged with desk-channel: healthy 1 times over 1m6s - messenger on novox: passed — judged with desk-channel: healthy 1 times over 1m6s - telegram on novox: passed — judged with desk-channel: healthy 1 times over 1m6s - claude-code on the rest running it: sent - desk-channel on the rest running it: sent - mesh-knowledge on the rest running it: sent - messenger on the rest running it: sent - telegram on the rest running it: sent **Transitions** - 2026-10-13 18:35 (new) → proposed (announced): novox/mesh-catalog#278's head announced - 2026-10-13 18:42 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit - 2026-10-13 18:42 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail - 2026-10-13 19:11 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move - 2026-10-13 19:11 published → delivering (go): its walk started: let go by this owner in its group's order, by a person, or on the controller's own path — not a failed walk that carried a later commit for it, after which it waits for a walk of its own commit - 2026-10-13 19:17 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`.
Author
Contributor

Merge check at ea1dfdce
Judged: head ea1dfdce5bc7 merged into trunk 5f491e0c097d; read beside it: mesh-controller 6f1a05366c1d, mesh-controller-main 6f1a05366c1d, mesh-host 0e92ef3d1b21, mesh-tools 954e1a53eef9

  • mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: claude-code, desk-channel, mesh-knowledge, messenger, telegram)
  • mesh/repo-check: PASS — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)

Delivery plan — builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, novox, shanks; no bus step

  • tier 0: claude-code, desk-channel, mesh-knowledge, messenger, telegram
  • ace: receives claude-code
  • g14: receives claude-code
  • novox: receives claude-code, desk-channel, mesh-knowledge, messenger, telegram
  • shanks: receives claude-code
  • claude-code keeps data (ADR 0233): what it holds is backed up before it moves
  • grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before claude-code is judged on its first machine
  • read by no module's build: modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go, modules/telegram/cmd/telegram/render_test.go

Run by the build seat on novox as build-1791902224469986315 (builds --log build-1791902224469986315).

--- the gate: claude-code, desk-channel, mesh-knowledge, messenger, telegram
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)
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)
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
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)
telegram: ok, 1 tool(s), keeps state offset, messages
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 3
5 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 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-13T14:32:41Z 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-13T14:32:41Z

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 5 module(s) in 1 tier(s): claude-code, desk-channel, mesh-knowledge, messenger, telegram

notes:
  - modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go and modules/telegram/cmd/telegram/render_test.go read by no module's build, and rebuild nothing (issue 280)
--- 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 46758 strings of 718 files
ok  	git.novox.be/novox/mesh-catalog/checks/agenthome	0.014s
agent-home: no archive and no file written into under the agent's home
ok  	git.novox.be/novox/mesh-catalog/checks/secrets	0.012s
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.009s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 66, as kept
ok  	git.novox.be/novox/mesh-catalog/checks/deps	0.227s
testing modules/claude-code
ok  	claude-code/cmd/claude-code	8.793s
testing modules/desk-channel
ok  	deskchannel/cmd/desk-channel	1.014s
testing modules/mesh-knowledge
ok  	mesh-knowledge/cmd/mesh-knowledge	136.504s
testing modules/messenger
ok  	messenger/cmd/messenger	2.381s
testing modules/telegram
ok  	telegram/cmd/telegram	1.066s
--- its merge-check-typescript.sh (typescript toolchain)
**Merge check** at `ea1dfdce` Judged: head `ea1dfdce5bc7` merged into trunk `5f491e0c097d`; read beside it: mesh-controller `6f1a05366c1d`, mesh-controller-main `6f1a05366c1d`, mesh-host `0e92ef3d1b21`, mesh-tools `954e1a53eef9` - `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: claude-code, desk-channel, mesh-knowledge, messenger, telegram) - `mesh/repo-check`: **PASS** — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript) **Delivery plan** — builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, novox, shanks; no bus step - tier 0: claude-code, desk-channel, mesh-knowledge, messenger, telegram - ace: receives claude-code - g14: receives claude-code - novox: receives claude-code, desk-channel, mesh-knowledge, messenger, telegram - shanks: receives claude-code - claude-code keeps data (ADR 0233): what it holds is backed up before it moves - grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before claude-code is judged on its first machine - read by no module's build: modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go, modules/telegram/cmd/telegram/render_test.go Run by the build seat on novox as `build-1791902224469986315` (`builds --log build-1791902224469986315`). ``` --- the gate: claude-code, desk-channel, mesh-knowledge, messenger, telegram 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) 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) 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 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) telegram: ok, 1 tool(s), keeps state offset, messages long-running resources without health: 0 files asking for a setting without saying whether it is trusted: 3 5 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 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-13T14:32:41Z 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-13T14:32:41Z 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 5 module(s) in 1 tier(s): claude-code, desk-channel, mesh-knowledge, messenger, telegram notes: - modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go and modules/telegram/cmd/telegram/render_test.go read by no module's build, and rebuild nothing (issue 280) --- 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 46758 strings of 718 files ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.014s agent-home: no archive and no file written into under the agent's home ok git.novox.be/novox/mesh-catalog/checks/secrets 0.012s 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.009s paths: no module names another's state on its machine (3 known, listed to go) long-running resources without health: 66, as kept ok git.novox.be/novox/mesh-catalog/checks/deps 0.227s testing modules/claude-code ok claude-code/cmd/claude-code 8.793s testing modules/desk-channel ok deskchannel/cmd/desk-channel 1.014s testing modules/mesh-knowledge ok mesh-knowledge/cmd/mesh-knowledge 136.504s testing modules/messenger ok messenger/cmd/messenger 2.381s testing modules/telegram ok telegram/cmd/telegram 1.066s --- its merge-check-typescript.sh (typescript toolchain) ```
mesh-admin left a comment
Author
Contributor

Verdict: approve at ea1dfdce5b

Independent review (issues 383 and 639, ADR 0345). The approval covers this PR's own content only. Its delivery-group partner mesh-controller#304 has a blocking finding: a settings proposal with more than 3 keys never shows the values of keys 3 and later, not even in the note. Fixing that may need a router change here so the whole words can reach the note. The router currently holds Details to the full content rule (messenger holder.go:893). If it does, this head changes and needs a new review. Do not merge the group before #304 is fixed. The checks are also out of date.

Security of the tap check (telegram channel.go:98, :354): sound.

  • wordsDigest collapses runs of whitespace only. Every word and its order still count, so a tap on altered words is refused (the PR's test changes "two" to "three").
  • The linesDigest fallback accepts nothing beyond what wordsDigest would. A match needs TrimSpace(x) to equal the collapsed text, and then both digests agree.
  • A warrant binds the ask's options and acts, not the text, so the text check cannot be used to replay a warrant against other words.
  • The remaining gap is not new and needs the bot token: someone holding it can edit with formatting, for example a spoiler, or move lines into a collapsed blockquote, and keep the plain words. Telegram gives text back without entities, so a tap still matches. This was already possible without parse_mode.

HTML escaping: every path is escaped. render.go escapes the title, every body line (inside <code> too) and the note inside the blockquote (:93). reply and the 'Replaced by' edit are escaped as well. Bot.Send and Bot.Edit (bot.go) are the only text calls. The test covers '<' and '&' in the title and the reply. Minor: no test puts '<' in the note.

Open asks at deploy:

  • mesh-knowledge OperatorAsk.Form and claude-code Proposal.Form and Question.Form read 0 for an existing ask, which is composed in its listed form.
  • The claude-code test shows the older form composes a different digest from the glance form, and that the older one is kept.
  • A message shown before the change is still tapped through linesDigest (TestATapOnAMessageShownBeforeIsStillTaken).

Minor findings, not blocking:

  • telegram render.go:56: when the body alone would pass 4096 characters, the whole note is dropped, including the fingerprint and "who asked". ADR 0345 clause 2 says "nothing of the note is dropped". This is only reachable above 4096 characters.
  • claude-code during a walk: a node still on old code ignores form and composes listedAsk for a glance proposal. Its warrant check fails on that node until it updates. This is transient.
  • An instructions proposal's summary is the proposer's own words, shown above a text that sits in the collapsed note, and nothing checks that the two agree. This is as clause 7 decides, so the risk was accepted there.
  • The ADR 0343 rendering test (telegram render_test.go) feeds a hand-built message. The router side of the same ask is held in messenger glance_test.go, so the pair covers clause 9.
  • An older channel drops Note silently, because Go's JSON ignores unknown fields. The messenger and the channels must therefore move in the same walk, which this PR does.

Tests (niced): messenger, telegram, desk-channel, mesh-knowledge and claude-code all pass. I put each module's PR tests on main's code, and every one fails there (build: Note, partsOf, linesDigest, Brief, AskGlance, Details and Glance are undefined).

Statuses at this head: mesh/merge-gate PENDING ("out of date: judged against trunk 5f491e0c09, the trunk is now 4d15a155e634; judged again on a recheck or when it is merged"), mesh/repo-check PENDING (same words), mesh/delivery PENDING ("checking"), mesh/delivery-group PENDING ("group fix/383-an-ask-reads-at-a-glance checking: composed check out of date: novox/mesh-catalog@ea1dfdce5b was judged against trunk 5f491…").

Verdict: approve at ea1dfdce5bc7973a56d491534af7031f38878774 Independent review (issues 383 and 639, ADR 0345). The approval covers this PR's own content only. Its delivery-group partner mesh-controller#304 has a blocking finding: a settings proposal with more than 3 keys never shows the values of keys 3 and later, not even in the note. Fixing that may need a router change here so the whole words can reach the note. The router currently holds Details to the full content rule (messenger holder.go:893). If it does, this head changes and needs a new review. Do not merge the group before #304 is fixed. The checks are also out of date. Security of the tap check (telegram channel.go:98, :354): sound. - `wordsDigest` collapses runs of whitespace only. Every word and its order still count, so a tap on altered words is refused (the PR's test changes "two" to "three"). - The `linesDigest` fallback accepts nothing beyond what `wordsDigest` would. A match needs TrimSpace(x) to equal the collapsed text, and then both digests agree. - A warrant binds the ask's options and acts, not the text, so the text check cannot be used to replay a warrant against other words. - The remaining gap is not new and needs the bot token: someone holding it can edit with formatting, for example a spoiler, or move lines into a collapsed blockquote, and keep the plain words. Telegram gives `text` back without entities, so a tap still matches. This was already possible without parse_mode. HTML escaping: every path is escaped. render.go escapes the title, every body line (inside `<code>` too) and the note inside the blockquote (:93). `reply` and the 'Replaced by' edit are escaped as well. Bot.Send and Bot.Edit (bot.go) are the only text calls. The test covers '<' and '&' in the title and the reply. Minor: no test puts '<' in the note. Open asks at deploy: - mesh-knowledge `OperatorAsk.Form` and claude-code `Proposal.Form` and `Question.Form` read 0 for an existing ask, which is composed in its listed form. - The claude-code test shows the older form composes a different digest from the glance form, and that the older one is kept. - A message shown before the change is still tapped through `linesDigest` (TestATapOnAMessageShownBeforeIsStillTaken). Minor findings, not blocking: - telegram render.go:56: when the body alone would pass 4096 characters, the whole note is dropped, including the fingerprint and "who asked". ADR 0345 clause 2 says "nothing of the note is dropped". This is only reachable above 4096 characters. - claude-code during a walk: a node still on old code ignores `form` and composes `listedAsk` for a glance proposal. Its warrant check fails on that node until it updates. This is transient. - An instructions proposal's `summary` is the proposer's own words, shown above a text that sits in the collapsed note, and nothing checks that the two agree. This is as clause 7 decides, so the risk was accepted there. - The ADR 0343 rendering test (telegram render_test.go) feeds a hand-built message. The router side of the same ask is held in messenger glance_test.go, so the pair covers clause 9. - An older channel drops `Note` silently, because Go's JSON ignores unknown fields. The messenger and the channels must therefore move in the same walk, which this PR does. Tests (niced): messenger, telegram, desk-channel, mesh-knowledge and claude-code all pass. I put each module's PR tests on main's code, and every one fails there (build: Note, partsOf, linesDigest, Brief, AskGlance, Details and Glance are undefined). Statuses at this head: mesh/merge-gate PENDING ("out of date: judged against trunk 5f491e0c097d, the trunk is now 4d15a155e634; judged again on a recheck or when it is merged"), mesh/repo-check PENDING (same words), mesh/delivery PENDING ("checking"), mesh/delivery-group PENDING ("group fix/383-an-ask-reads-at-a-glance checking: composed check out of date: novox/mesh-catalog@ea1dfdce5bc7 was judged against trunk 5f491…").
jschoubben force-pushed fix/383-an-ask-reads-at-a-glance from ea1dfdce5b to 5dbf53e758 2026-10-13 15:04:49 +00:00 Compare
Author
Contributor

New head 5dbf53e758, rebased on main, with one more commit for the review of mesh-controller #304 and the minor points here.

  • messenger: on a kind that proves who answers, the note shows the ask's WholeDetails in place of its Details. It is held to the secret rule alone, and an ask whose whole details carry a secret's shape is refused. Test: TestEveryKeyAndItsWholeValueIsInTheNoteWhereTheSenderIsProven (5 keys, a 300-character value: every key and full value is in the Telegram note, masked on the desk).
  • telegram: the note is never dropped above 4096 characters. The body is cut first and the cut is said; the note is cut only when the title and note alone do not fit, and that is said too. Tests: TestALongBodyIsCutBeforeTheNote, TestTheNoteIsEscaped ('<', '>', '&' and a stray </blockquote> in the note).
  • SDK at mesh-sdk f474544 (WholeDetails). Decision: ADR 0347. Local merge-check.sh with MESH_GATE and the five modules passed.
New head 5dbf53e75840, rebased on main, with one more commit for the review of mesh-controller #304 and the minor points here. - **messenger**: on a kind that proves who answers, the note shows the ask's `WholeDetails` in place of its Details. It is held to the secret rule alone, and an ask whose whole details carry a secret's shape is refused. Test: `TestEveryKeyAndItsWholeValueIsInTheNoteWhereTheSenderIsProven` (5 keys, a 300-character value: every key and full value is in the Telegram note, masked on the desk). - **telegram**: the note is never dropped above 4096 characters. The body is cut first and the cut is said; the note is cut only when the title and note alone do not fit, and that is said too. Tests: `TestALongBodyIsCutBeforeTheNote`, `TestTheNoteIsEscaped` ('<', '>', '&' and a stray `</blockquote>` in the note). - SDK at mesh-sdk f474544 (`WholeDetails`). Decision: ADR 0347. Local merge-check.sh with MESH_GATE and the five modules passed.
Author
Contributor

Merge check at 5dbf53e7
Judged: head 5dbf53e75840 merged into trunk e209d46faf3d; read beside it: mesh-controller 6f1a05366c1d, mesh-controller-main 6f1a05366c1d, mesh-host 0e92ef3d1b21, mesh-tools 954e1a53eef9

  • mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: claude-code, desk-channel, mesh-knowledge, messenger, telegram)
  • mesh/repo-check: PASS — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)

Delivery plan — builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, novox, shanks; no bus step

  • tier 0: claude-code, desk-channel, mesh-knowledge, messenger, telegram
  • ace: receives claude-code
  • g14: receives claude-code
  • novox: receives claude-code, desk-channel, mesh-knowledge, messenger, telegram
  • shanks: receives claude-code
  • claude-code keeps data (ADR 0233): what it holds is backed up before it moves
  • grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before claude-code is judged on its first machine
  • read by no module's build: modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go, modules/telegram/cmd/telegram/render_test.go

Run by the build seat on ace as build-1791903913138216999 (builds --log build-1791903913138216999).

--- the gate: claude-code, desk-channel, mesh-knowledge, messenger, telegram
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)
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)
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
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)
telegram: ok, 1 tool(s), keeps state offset, messages
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 3
5 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 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-13T14:52:41Z 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-13T14:52:41Z

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 5 module(s) in 1 tier(s): claude-code, desk-channel, mesh-knowledge, messenger, telegram

notes:
  - modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go and modules/telegram/cmd/telegram/render_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok  	git.novox.be/novox/mesh-catalog/checks/words	0.002s
words: 12 retired words and 70 daemons' lines, none in the 46786 strings of 718 files
ok  	git.novox.be/novox/mesh-catalog/checks/agenthome	0.012s
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.006s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 66, as kept
ok  	git.novox.be/novox/mesh-catalog/checks/deps	0.217s
testing modules/claude-code
ok  	claude-code/cmd/claude-code	5.733s
testing modules/desk-channel
ok  	deskchannel/cmd/desk-channel	1.012s
testing modules/mesh-knowledge
ok  	mesh-knowledge/cmd/mesh-knowledge	101.289s
testing modules/messenger
ok  	messenger/cmd/messenger	2.028s
testing modules/telegram
ok  	telegram/cmd/telegram	1.063s
--- its merge-check-typescript.sh (typescript toolchain)

Out of date when it landed: out of date: judged against trunk e209d46faf, the trunk is now 9c166398f204; judged again on a recheck or when it is merged

**Merge check** at `5dbf53e7` Judged: head `5dbf53e75840` merged into trunk `e209d46faf3d`; read beside it: mesh-controller `6f1a05366c1d`, mesh-controller-main `6f1a05366c1d`, mesh-host `0e92ef3d1b21`, mesh-tools `954e1a53eef9` - `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: claude-code, desk-channel, mesh-knowledge, messenger, telegram) - `mesh/repo-check`: **PASS** — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript) **Delivery plan** — builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, novox, shanks; no bus step - tier 0: claude-code, desk-channel, mesh-knowledge, messenger, telegram - ace: receives claude-code - g14: receives claude-code - novox: receives claude-code, desk-channel, mesh-knowledge, messenger, telegram - shanks: receives claude-code - claude-code keeps data (ADR 0233): what it holds is backed up before it moves - grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before claude-code is judged on its first machine - read by no module's build: modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go, modules/telegram/cmd/telegram/render_test.go Run by the build seat on ace as `build-1791903913138216999` (`builds --log build-1791903913138216999`). ``` --- the gate: claude-code, desk-channel, mesh-knowledge, messenger, telegram 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) 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) 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 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) telegram: ok, 1 tool(s), keeps state offset, messages long-running resources without health: 0 files asking for a setting without saying whether it is trusted: 3 5 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 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-13T14:52:41Z 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-13T14:52:41Z 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 5 module(s) in 1 tier(s): claude-code, desk-channel, mesh-knowledge, messenger, telegram notes: - modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go and modules/telegram/cmd/telegram/render_test.go read by no module's build, and rebuild nothing (issue 280) --- its merge-check.sh (go toolchain) ok git.novox.be/novox/mesh-catalog/checks/words 0.002s words: 12 retired words and 70 daemons' lines, none in the 46786 strings of 718 files ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.012s 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.006s paths: no module names another's state on its machine (3 known, listed to go) long-running resources without health: 66, as kept ok git.novox.be/novox/mesh-catalog/checks/deps 0.217s testing modules/claude-code ok claude-code/cmd/claude-code 5.733s testing modules/desk-channel ok deskchannel/cmd/desk-channel 1.012s testing modules/mesh-knowledge ok mesh-knowledge/cmd/mesh-knowledge 101.289s testing modules/messenger ok messenger/cmd/messenger 2.028s testing modules/telegram ok telegram/cmd/telegram 1.063s --- its merge-check-typescript.sh (typescript toolchain) ``` **Out of date when it landed**: out of date: judged against trunk e209d46faf3d, the trunk is now 9c166398f204; judged again on a recheck or when it is merged
jschoubben added 2 commits 2026-10-13 15:16:52 +00:00
The operator would not read the Telegram ask for ADR 0343: thirty plain lines, every clause on one, no bold,
no summary. A settings proposal was the same wall of text, its values masked so the approval was blind.

- messenger: an ask's message is the asker's headline and explanation alone; who asked and when, what each
  answer does, the expiry, where else it is answered and the asker's Details travel as the message's note
  (asks.Message.Note). Answered, the message is one line, "You chose Approve at 16:06 on Telegram ·
  <headline>". An explanation that does not read at a glance (asks.Glance) is shown and logged. On a kind
  that proves who answers, an ask's values are shown whole (asks.Ask.Whole), held to the secret rule alone
  (from the earlier work on issue 383, #178).
- telegram: every message in HTML, never reworded: the title bold, a key line monospace, the note apart in
  a collapsed blockquote; markup escaped. A tap is compared by its words, whitespace aside, and a message
  shown before is still compared by the digest it was kept under.
- desk-channel: the note follows the body.
- mesh-knowledge: a record that needs the operator carries a brief (headline, summary, at most three
  points), the 30th per-record rule; its ask shows the brief and never the clauses. An ask made before is
  composed again as it was asked (form), so its warrant still holds.
- claude-code: an instructions proposal's explanation is one summary line (the proposer's, or the
  module's), its text in the Details; a question's context is at most 300 characters and its recommendation
  one point. Older proposals and questions keep their form.

The SDK is pinned at mesh-sdk 9588871 (fix/639-an-ask-reads-at-a-glance), which adds Message.Note and
asks.Glance.
Every value an approval sets is in the note, whole where the sender is proven; the note is kept whole (issue 383)
mesh/merge-gate head bb5a342863ee merged into trunk 9c166398f204 — pass: builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, …
mesh/repo-check head bb5a342863ee merged into trunk 9c166398f204 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery-group group fix/383-an-ask-reads-at-a-glance checking: 1 of 2 member(s) ready
mesh/delivery superseded: a newer head of the same pull request
bb5a342863
The review of mesh-controller #304: a proposal of more than three keys showed only the names of the rest,
and its Details could carry no value, so Approve bound values the operator never saw. The router now
shows an ask's WholeDetails in the note in place of its Details on a kind that proves who answers, held
to the secret rule alone, and refuses an ask whose whole details carry a secret's shape. Telegram keeps
the note whole when a message is too long, cutting the body first and saying so, and escapes the note
as every other part. SDK at mesh-sdk f474544.
jschoubben force-pushed fix/383-an-ask-reads-at-a-glance from 5dbf53e758 to bb5a342863 2026-10-13 15:16:52 +00:00 Compare
Author
Contributor

Merge check at bb5a3428
Judged: head bb5a342863ee merged into trunk 9c166398f204; read beside it: mesh-controller 6f1a05366c1d, mesh-controller-main 6f1a05366c1d, mesh-host 0e92ef3d1b21, mesh-tools 954e1a53eef9

  • mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: claude-code, desk-channel, mesh-knowledge, messenger, telegram)
  • mesh/repo-check: PASS — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)

Delivery plan — builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, novox, shanks; no bus step

  • tier 0: claude-code, desk-channel, mesh-knowledge, messenger, telegram
  • ace: receives claude-code
  • g14: receives claude-code
  • novox: receives claude-code, desk-channel, mesh-knowledge, messenger, telegram
  • shanks: receives claude-code
  • claude-code keeps data (ADR 0233): what it holds is backed up before it moves
  • grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before claude-code is judged on its first machine
  • read by no module's build: modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go, modules/telegram/cmd/telegram/render_test.go

Run by the build seat on ace as build-1791904626852455819 (builds --log build-1791904626852455819).

--- the gate: claude-code, desk-channel, mesh-knowledge, messenger, telegram
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)
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)
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
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)
telegram: ok, 1 tool(s), keeps state offset, messages
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 3
5 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 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-13T15:15:17Z 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-13T15:15:17Z

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 5 module(s) in 1 tier(s): claude-code, desk-channel, mesh-knowledge, messenger, telegram

notes:
  - modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go and modules/telegram/cmd/telegram/render_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok  	git.novox.be/novox/mesh-catalog/checks/words	0.002s
words: 12 retired words and 70 daemons' lines, none in the 46758 strings of 718 files
ok  	git.novox.be/novox/mesh-catalog/checks/agenthome	0.012s
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.006s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 66, as kept
ok  	git.novox.be/novox/mesh-catalog/checks/deps	0.215s
testing modules/claude-code
ok  	claude-code/cmd/claude-code	5.794s
testing modules/desk-channel
ok  	deskchannel/cmd/desk-channel	1.011s
testing modules/mesh-knowledge
ok  	mesh-knowledge/cmd/mesh-knowledge	101.459s
testing modules/messenger
ok  	messenger/cmd/messenger	2.041s
testing modules/telegram
ok  	telegram/cmd/telegram	1.058s
--- its merge-check-typescript.sh (typescript toolchain)
**Merge check** at `bb5a3428` Judged: head `bb5a342863ee` merged into trunk `9c166398f204`; read beside it: mesh-controller `6f1a05366c1d`, mesh-controller-main `6f1a05366c1d`, mesh-host `0e92ef3d1b21`, mesh-tools `954e1a53eef9` - `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: claude-code, desk-channel, mesh-knowledge, messenger, telegram) - `mesh/repo-check`: **PASS** — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript) **Delivery plan** — builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, novox, shanks; no bus step - tier 0: claude-code, desk-channel, mesh-knowledge, messenger, telegram - ace: receives claude-code - g14: receives claude-code - novox: receives claude-code, desk-channel, mesh-knowledge, messenger, telegram - shanks: receives claude-code - claude-code keeps data (ADR 0233): what it holds is backed up before it moves - grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before claude-code is judged on its first machine - read by no module's build: modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go, modules/telegram/cmd/telegram/render_test.go Run by the build seat on ace as `build-1791904626852455819` (`builds --log build-1791904626852455819`). ``` --- the gate: claude-code, desk-channel, mesh-knowledge, messenger, telegram 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) 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) 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 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) telegram: ok, 1 tool(s), keeps state offset, messages long-running resources without health: 0 files asking for a setting without saying whether it is trusted: 3 5 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 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-13T15:15:17Z 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-13T15:15:17Z 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 5 module(s) in 1 tier(s): claude-code, desk-channel, mesh-knowledge, messenger, telegram notes: - modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go and modules/telegram/cmd/telegram/render_test.go read by no module's build, and rebuild nothing (issue 280) --- its merge-check.sh (go toolchain) ok git.novox.be/novox/mesh-catalog/checks/words 0.002s words: 12 retired words and 70 daemons' lines, none in the 46758 strings of 718 files ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.012s 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.006s paths: no module names another's state on its machine (3 known, listed to go) long-running resources without health: 66, as kept ok git.novox.be/novox/mesh-catalog/checks/deps 0.215s testing modules/claude-code ok claude-code/cmd/claude-code 5.794s testing modules/desk-channel ok deskchannel/cmd/desk-channel 1.011s testing modules/mesh-knowledge ok mesh-knowledge/cmd/mesh-knowledge 101.459s testing modules/messenger ok messenger/cmd/messenger 2.041s testing modules/telegram ok telegram/cmd/telegram 1.058s --- its merge-check-typescript.sh (typescript toolchain) ```
mesh-admin left a comment
Author
Contributor

Verdict: approve at bb5a342863

Independent review of the issue 383/639 group under ADR 0345 and ADR 0347. The code here is right. However, mesh-sdk #25 is asked to change its digest encoding, so this PR must re-pin the new SDK head in every module's go.mod/go.sum before it merges. That re-pin needs a fresh look at the pin only.

Checked:

  • (1) On an ask's own message, on a kind that proves who answers and holds a ticket, the note shows WholeDetails, held to CheckSecret (messenger holder.go:889-901, asks.go provenAsk). Everywhere else it shows Details under Check. The desk shows the note after the body (desk-channel desk.go). TestEveryKeyAndItsWholeValueIsInTheNoteWhereTheSenderIsProven covers both.
  • (2) TakeAsk refuses an ask whose Whole or WholeDetails carry a secret's shape (messenger asks.go:494). A tap is compared by a whitespace-normalised digest of the plain words. A message shown before this change still matches through linesDigest (telegram channel.go:93-108, :354). A hash preimage would be needed to pass either digest with other words.
  • (3) Escaping: every Send and Edit goes through shown.html() or escape() (channel.go:252, 296, 304, 462), and escape covers &, < and >. I probed a note holding </blockquote><a href=...> and it rendered as text, one blockquote, no link.
  • Cutting (ADR 0347 §5): partsOf cuts the body first and cuts the note only when the title and note alone do not fit. Each cut says itself. I probed 3000/2000 and 5 + 5000 characters; both give exactly 4096.
  • Tests: messenger, telegram, desk-channel, claude-code and mesh-knowledge all pass at the head (run niced). The new tests fail on main (build) and on eadf301: TestALongBodyIsCutBeforeTheNote fails there, and the messenger whole-details tests do not build.

Not blocking:

  • messenger holder.go:899 replaces a Details line that fails its rule with "(a line carrying … is withheld here)", which drops the key's name. ADR 0347 §2 has the asker withhold the value under its key, so with a correct asker this line should not occur. But the controller can reach it today (see the review on mesh-controller #304: a key named password, past the second). Keeping the key's name, when the line starts with "+ key:", would make the router's fallback match §3.
  • telegram render.go partsOf does not bound the title. A title over 4096 characters gives a message Telegram rejects. Headlines are bounded upstream, so this is theoretical.

Statuses at this head: mesh/merge-gate success ("head bb5a342863 merged into trunk 9c166398f2, pass"), mesh/repo-check success, mesh/delivery success ("ready: it delivers once merged"), mesh/delivery-group success ("group fix/383-an-ask-reads-at-a-glance ready: every member ready, and composed together they pass").

Verdict: approve at bb5a342863ee2b25373e9bb96722a6921bb92b7b Independent review of the issue 383/639 group under ADR 0345 and ADR 0347. The code here is right. However, mesh-sdk #25 is asked to change its digest encoding, so this PR must re-pin the new SDK head in every module's go.mod/go.sum before it merges. That re-pin needs a fresh look at the pin only. Checked: - (1) On an ask's own message, on a kind that proves who answers and holds a ticket, the note shows WholeDetails, held to CheckSecret (messenger holder.go:889-901, asks.go provenAsk). Everywhere else it shows Details under Check. The desk shows the note after the body (desk-channel desk.go). TestEveryKeyAndItsWholeValueIsInTheNoteWhereTheSenderIsProven covers both. - (2) TakeAsk refuses an ask whose Whole or WholeDetails carry a secret's shape (messenger asks.go:494). A tap is compared by a whitespace-normalised digest of the plain words. A message shown before this change still matches through linesDigest (telegram channel.go:93-108, :354). A hash preimage would be needed to pass either digest with other words. - (3) Escaping: every Send and Edit goes through shown.html() or escape() (channel.go:252, 296, 304, 462), and escape covers &, < and >. I probed a note holding `</blockquote><a href=...>` and it rendered as text, one blockquote, no link. - Cutting (ADR 0347 §5): partsOf cuts the body first and cuts the note only when the title and note alone do not fit. Each cut says itself. I probed 3000/2000 and 5 + 5000 characters; both give exactly 4096. - Tests: messenger, telegram, desk-channel, claude-code and mesh-knowledge all pass at the head (run niced). The new tests fail on main (build) and on eadf301: TestALongBodyIsCutBeforeTheNote fails there, and the messenger whole-details tests do not build. Not blocking: - messenger holder.go:899 replaces a Details line that fails its rule with "(a line carrying … is withheld here)", which drops the key's name. ADR 0347 §2 has the asker withhold the value under its key, so with a correct asker this line should not occur. But the controller can reach it today (see the review on mesh-controller #304: a key named password, past the second). Keeping the key's name, when the line starts with "+ key:", would make the router's fallback match §3. - telegram render.go partsOf does not bound the title. A title over 4096 characters gives a message Telegram rejects. Headlines are bounded upstream, so this is theoretical. Statuses at this head: mesh/merge-gate success ("head bb5a342863ee merged into trunk 9c166398f204, pass"), mesh/repo-check success, mesh/delivery success ("ready: it delivers once merged"), mesh/delivery-group success ("group fix/383-an-ask-reads-at-a-glance ready: every member ready, and composed together they pass").
jschoubben added 1 commit 2026-10-13 18:35:20 +00:00
A withheld change line in the note keeps its key's name; SDK at 5933eb7 (the review of mesh-controller #304)
mesh/merge-gate head f09daabec3a8 merged into trunk 9c166398f204 — pass: builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, …
mesh/repo-check head f09daabec3a8 merged into trunk 9c166398f204 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered
mesh/delivery-group group fix/383-an-ask-reads-at-a-glance delivered: every member is delivered
f09daabec3
The router's fallback said a refused note line as "(a line carrying … is withheld here)", so the operator
could not tell which setting held a value they were not shown. A change's line now keeps its key; any other
line, or one whose key is refused too, is said withheld whole. The SDK pin moves to mesh-sdk 5933eb7, where
no two asks digest the same.
Author
Contributor

New head f09daabec3. The router's fallback for a refused note line now keeps a change line's key (withheldLine): + password (a value carrying a value given to a secret's name is withheld here). Any other line, or one whose key is refused too, is still withheld whole. Test: TestAWithheldChangeLineKeepsItsKey. All five modules are re-pinned to mesh-sdk 5933eb7. Local merge-check.sh passed.

New head f09daabec3a8. The router's fallback for a refused note line now keeps a change line's key (`withheldLine`): `+ password (a value carrying a value given to a secret's name is withheld here)`. Any other line, or one whose key is refused too, is still withheld whole. Test: `TestAWithheldChangeLineKeepsItsKey`. All five modules are re-pinned to mesh-sdk 5933eb7. Local merge-check.sh passed.
Author
Contributor

Merge check at f09daabe
Judged: head f09daabec3a8 merged into trunk 9c166398f204; read beside it: mesh-controller 9f3aa91e812b, mesh-controller-main 332fbaa9b175, mesh-host 0e92ef3d1b21, mesh-tools 954e1a53eef9

  • mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: claude-code, desk-channel, mesh-knowledge, messenger, telegram)
  • mesh/repo-check: PASS — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)

Delivery plan — builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, novox, shanks; no bus step

  • tier 0: claude-code, desk-channel, mesh-knowledge, messenger, telegram
  • ace: receives claude-code
  • g14: receives claude-code
  • novox: receives claude-code, desk-channel, mesh-knowledge, messenger, telegram
  • shanks: receives claude-code
  • claude-code keeps data (ADR 0233): what it holds is backed up before it moves
  • grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before claude-code is judged on its first machine
  • read by no module's build: modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go, modules/telegram/cmd/telegram/render_test.go

Run by the build seat on ace as build-1791916538403302422 (builds --log build-1791916538403302422).

--- the gate: claude-code, desk-channel, mesh-knowledge, messenger, telegram
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)
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)
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
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)
telegram: ok, 1 tool(s), keeps state offset, messages
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 3
5 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 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-13T18:36:27Z 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-13T18:36:27Z

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 5 module(s) in 1 tier(s): claude-code, desk-channel, mesh-knowledge, messenger, telegram

notes:
  - modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go and modules/telegram/cmd/telegram/render_test.go read by no module's build, and rebuild nothing (issue 280)
--- 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 46762 strings of 718 files
ok  	git.novox.be/novox/mesh-catalog/checks/agenthome	0.012s
agent-home: no archive and no file written into under the agent's home
ok  	git.novox.be/novox/mesh-catalog/checks/secrets	0.012s
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)
long-running resources without health: 66, as kept
ok  	git.novox.be/novox/mesh-catalog/checks/deps	0.251s
testing modules/claude-code
ok  	claude-code/cmd/claude-code	6.623s
testing modules/desk-channel
ok  	deskchannel/cmd/desk-channel	1.013s
testing modules/mesh-knowledge
ok  	mesh-knowledge/cmd/mesh-knowledge	99.492s
testing modules/messenger
ok  	messenger/cmd/messenger	1.992s
testing modules/telegram
ok  	telegram/cmd/telegram	1.058s
--- its merge-check-typescript.sh (typescript toolchain)
**Merge check** at `f09daabe` Judged: head `f09daabec3a8` merged into trunk `9c166398f204`; read beside it: mesh-controller `9f3aa91e812b`, mesh-controller-main `332fbaa9b175`, mesh-host `0e92ef3d1b21`, mesh-tools `954e1a53eef9` - `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: claude-code, desk-channel, mesh-knowledge, messenger, telegram) - `mesh/repo-check`: **PASS** — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript) **Delivery plan** — builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, novox, shanks; no bus step - tier 0: claude-code, desk-channel, mesh-knowledge, messenger, telegram - ace: receives claude-code - g14: receives claude-code - novox: receives claude-code, desk-channel, mesh-knowledge, messenger, telegram - shanks: receives claude-code - claude-code keeps data (ADR 0233): what it holds is backed up before it moves - grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before claude-code is judged on its first machine - read by no module's build: modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go, modules/telegram/cmd/telegram/render_test.go Run by the build seat on ace as `build-1791916538403302422` (`builds --log build-1791916538403302422`). ``` --- the gate: claude-code, desk-channel, mesh-knowledge, messenger, telegram 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) 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) 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 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) telegram: ok, 1 tool(s), keeps state offset, messages long-running resources without health: 0 files asking for a setting without saying whether it is trusted: 3 5 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 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-13T18:36:27Z 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-13T18:36:27Z 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 5 module(s) in 1 tier(s): claude-code, desk-channel, mesh-knowledge, messenger, telegram notes: - modules/claude-code/README.md, modules/claude-code/cmd/claude-code/proposals_test.go, modules/claude-code/cmd/claude-code/questions_test.go, modules/desk-channel/cmd/desk-channel/desk_test.go, modules/mesh-knowledge/README.md, modules/mesh-knowledge/cmd/mesh-knowledge/glance_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/review_test.go, modules/mesh-knowledge/cmd/mesh-knowledge/rules_test.go, modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go, modules/messenger/cmd/messenger/glance_test.go, modules/messenger/cmd/messenger/onemessage_test.go, modules/messenger/cmd/messenger/review_test.go, modules/messenger/cmd/messenger/whole_test.go, modules/telegram/README.md, modules/telegram/cmd/telegram/channel_test.go and modules/telegram/cmd/telegram/render_test.go read by no module's build, and rebuild nothing (issue 280) --- 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 46762 strings of 718 files ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.012s agent-home: no archive and no file written into under the agent's home ok git.novox.be/novox/mesh-catalog/checks/secrets 0.012s 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) long-running resources without health: 66, as kept ok git.novox.be/novox/mesh-catalog/checks/deps 0.251s testing modules/claude-code ok claude-code/cmd/claude-code 6.623s testing modules/desk-channel ok deskchannel/cmd/desk-channel 1.013s testing modules/mesh-knowledge ok mesh-knowledge/cmd/mesh-knowledge 99.492s testing modules/messenger ok messenger/cmd/messenger 1.992s testing modules/telegram ok telegram/cmd/telegram 1.058s --- its merge-check-typescript.sh (typescript toolchain) ```
mesh-admin left a comment
Author
Contributor

Verdict: approve at f09daabec3

Re-review after review 226. The only change since bb5a342 is one commit:

  • Pin: messenger, telegram, desk-channel, claude-code and mesh-knowledge all pin mesh-sdk 5933eb757d44, the approved head of mesh-sdk #25.
  • Withheld lines: messenger holder.go:899 now calls withheldLine (holder.go:1150-1165). A refused change line ("+ key: …") keeps its key, and the named form is itself checked against the same rule; otherwise the whole line is said withheld. A key shaped like a secret falls back to the whole-line form, so it is never echoed. TestAWithheldChangeLineKeepsItsKey covers four shapes and does not build on bb5a342.
  • Tests: all five modules pass at this head (run niced).

Statuses at this head: mesh/merge-gate success ("head f09daabec3 merged into trunk 9c166398f2 — pass: builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, …"), mesh/repo-check success ("… pass: its merge-check.sh passed …"), mesh/delivery success ("ready: it delivers once merged"), mesh/delivery-group success ("group fix/383-an-ask-reads-at-a-glance ready: every member ready, and composed together they pass", 18:55:39Z, after the new controller and SDK heads).

Verdict: approve at f09daabec3a8791b4d2ba44c4d5102ed40a3f570 Re-review after review 226. The only change since bb5a342 is one commit: - Pin: messenger, telegram, desk-channel, claude-code and mesh-knowledge all pin mesh-sdk 5933eb757d44, the approved head of mesh-sdk #25. - Withheld lines: messenger holder.go:899 now calls withheldLine (holder.go:1150-1165). A refused change line ("+ key: …") keeps its key, and the named form is itself checked against the same rule; otherwise the whole line is said withheld. A key shaped like a secret falls back to the whole-line form, so it is never echoed. TestAWithheldChangeLineKeepsItsKey covers four shapes and does not build on bb5a342. - Tests: all five modules pass at this head (run niced). Statuses at this head: mesh/merge-gate success ("head f09daabec3a8 merged into trunk 9c166398f204 — pass: builds claude-code, desk-channel, mesh-knowledge, messenger, telegram → ace, g14, …"), mesh/repo-check success ("… pass: its merge-check.sh passed …"), mesh/delivery success ("ready: it delivers once merged"), mesh/delivery-group success ("group fix/383-an-ask-reads-at-a-glance ready: every member ready, and composed together they pass", 18:55:39Z, after the new controller and SDK heads).
mesh-admin merged commit faebc3569a into main 2026-10-13 19:02:21 +00:00
mesh-admin deleted branch fix/383-an-ask-reads-at-a-glance 2026-10-13 19:02:21 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-catalog#278