Issue 372 (tapping Approve or Decline on Telegram gives the operator no visible feedback).
What happened at 13:30 on 2026-10-10 (messenger journal, operator-channel.history, telegram.telegram_status): the two questions were sent at 13:25:33. Two taps at 13:30:34 and 13:30:36 were refused ("it belongs to no open message"): their tickets were held by no open message, so they were on older messages; a "That answer was not taken" message went to the chat for each. The Approve taps at 13:30:51 and 13:30:58 were recorded as warrants, and each question was edited (history: edited, telegram last_delivered 13:30:58, no failure logged). But the channel had acknowledged each tap at once with no text (answerTap(cb.ID, ""), before the router judged anything), so no toast; and the edit kept the question's title, removed the buttons and only added "Approve: chosen at 13:30 on Telegram" as the first body line. An edit rings nothing. So the operator saw no confirmation and only a subtle change.
The fix
messenger: once the ask's end is recorded (compare-and-set succeeded) and the asker told or not, and before the question is edited, the router replies to the choice where it was given: "You chose Approve: recorded, and claude-code was told." (or "…is told as soon as the bus takes it." when the bus refused the warrant). A refusal already replied with its reason. An ask's own message, once answered, has its outcome as its title: "You chose Approve at 13:30 on Telegram · ", then "Told to claude-code, which acts on it itself.", the explanation and when it was asked. Expiry reads "No longer answerable: nobody answered in time · ".
telegram: a tap's answerCallbackQuery waits for the router's reply to that tap and shows it as the toast (title and first body line, cut at 200 characters). A reply of one line is only the toast; one with a body (a refusal's reason, Details) is also sent to the chat. Without a reply in 8 seconds, the toast claims nothing ("Passed to the mesh, which has not decided yet…") and the late reply goes to the chat; a reply Telegram no longer takes as the acknowledgement also goes to the chat. A secret reply is never a toast. A tap that cannot be said to the router is acknowledged with "…Nothing was done."
(3) the follow-up: the asks protocol carries no result back from an asker to the router (only decided from router to asker). So the router says only what it knows: whether the asker was told. No second edit is made.
Reviewers' checklist
Feedback never claims success before the warrant is recorded: confirm runs inside closeAsk only after UpdateAsk succeeded; TestTheConfirmationNeverClaimsWhatDidNotHappen (store refuses the write: only the refusal, with "could not be recorded"; bus refuses the warrant: "is told as soon as the bus takes it"). Telegram never acknowledges before the router's word (TestATapIsAcknowledgedWithTheRoutersWordOnIt).
A refused tap says why: TestARefusedTapSaysWhyOnThePhoneAndInTheChat, TestARefusedAnswerSaysWhyInReplyToTheTap.
No double edits racing: one edit per close, as before (CAS); the toast is answerCallbackQuery, not an edit; a tap is acknowledged once (settleTap deletes under the lock; the timer after a reply does nothing). Order checked: confirmation, then the edit (TestAnApprovalIsConfirmedWhereItWasGivenAndThenTheQuestionSaysHowItEnded).
Tests fail with the fix removed: with asks.go/holder.go/selfact.go reverted, the 3 new messenger tests and 3 updated ones fail; with channel.go reverted, the telegram tests do not build (and the old code acknowledges before the router's word).
Desk: a desk click on an acknowledgement-level ask now also gets the quiet confirmation, shown where it was clicked.
Not touched: answers.go (issue 371's Details work).
go test -race passes for both modules; the words check passes. Do not merge without review.
Issue 372 (tapping Approve or Decline on Telegram gives the operator no visible feedback).
**What happened at 13:30 on 2026-10-10** (messenger journal, `operator-channel.history`, `telegram.telegram_status`): the two questions were sent at 13:25:33. Two taps at 13:30:34 and 13:30:36 were refused ("it belongs to no open message"): their tickets were held by no open message, so they were on older messages; a "That answer was not taken" message went to the chat for each. The Approve taps at 13:30:51 and 13:30:58 were recorded as warrants, and each question was edited (history: `edited`, telegram `last_delivered` 13:30:58, no failure logged). But the channel had acknowledged each tap at once with **no text** (`answerTap(cb.ID, "")`, before the router judged anything), so no toast; and the edit kept the question's **title**, removed the buttons and only added "Approve: chosen at 13:30 on Telegram" as the first body line. An edit rings nothing. So the operator saw no confirmation and only a subtle change.
**The fix**
- messenger: once the ask's end is recorded (compare-and-set succeeded) and the asker told or not, and before the question is edited, the router replies to the choice where it was given: "You chose Approve: recorded, and claude-code was told." (or "…is told as soon as the bus takes it." when the bus refused the warrant). A refusal already replied with its reason. An ask's own message, once answered, has its outcome as its title: "You chose Approve at 13:30 on Telegram · <headline>", then "Told to claude-code, which acts on it itself.", the explanation and when it was asked. Expiry reads "No longer answerable: nobody answered in time · <headline>".
- telegram: a tap's `answerCallbackQuery` waits for the router's reply to that tap and shows it as the toast (title and first body line, cut at 200 characters). A reply of one line is only the toast; one with a body (a refusal's reason, Details) is also sent to the chat. Without a reply in 8 seconds, the toast claims nothing ("Passed to the mesh, which has not decided yet…") and the late reply goes to the chat; a reply Telegram no longer takes as the acknowledgement also goes to the chat. A secret reply is never a toast. A tap that cannot be said to the router is acknowledged with "…Nothing was done."
- (3) the follow-up: the asks protocol carries no result back from an asker to the router (only `decided` from router to asker). So the router says only what it knows: whether the asker was told. No second edit is made.
**Reviewers' checklist**
- Feedback never claims success before the warrant is recorded: `confirm` runs inside `closeAsk` only after `UpdateAsk` succeeded; `TestTheConfirmationNeverClaimsWhatDidNotHappen` (store refuses the write: only the refusal, with "could not be recorded"; bus refuses the warrant: "is told as soon as the bus takes it"). Telegram never acknowledges before the router's word (`TestATapIsAcknowledgedWithTheRoutersWordOnIt`).
- A refused tap says why: `TestARefusedTapSaysWhyOnThePhoneAndInTheChat`, `TestARefusedAnswerSaysWhyInReplyToTheTap`.
- No double edits racing: one edit per close, as before (CAS); the toast is `answerCallbackQuery`, not an edit; a tap is acknowledged once (`settleTap` deletes under the lock; the timer after a reply does nothing). Order checked: confirmation, then the edit (`TestAnApprovalIsConfirmedWhereItWasGivenAndThenTheQuestionSaysHowItEnded`).
- Tests fail with the fix removed: with asks.go/holder.go/selfact.go reverted, the 3 new messenger tests and 3 updated ones fail; with channel.go reverted, the telegram tests do not build (and the old code acknowledges before the router's word).
- Desk: a desk click on an acknowledgement-level ask now also gets the quiet confirmation, shown where it was clicked.
- Not touched: answers.go (issue 371's Details work).
`go test -race` passes for both modules; the words check passes. Do not merge without review.
At 13:30 on 2026-10-10 the operator approved two questions on Telegram and saw
nothing happen: the channel acknowledged each tap with no words, before the
router had judged it, and the edit that removed the buttons kept the question's
title, adding only a line under it that rings nothing.
The router now answers a chosen option in reply to the tap, once the ask's end
is recorded and before the question is edited: "You chose Approve: recorded,
and claude-code was told." (or, when the bus did not take the warrant, that it
is told when it does). A refusal already replied with its reason. Telegram
holds a tap's acknowledgement for the router's word and shows it as the tap's
own toast; a word with a body (a refusal's reason, Details) also stays in the
chat. Without a word in 8 seconds the toast claims nothing, and the late word
goes to the chat. A secret is never a toast.
An ask's own message, once answered, carries its outcome as its title:
"You chose Approve at 13:30 on Telegram · <headline>", then whether the asker
was told. The asks protocol carries no result back from the asker, so nothing
more is claimed of what it did.
Deliverynovox/mesh-catalog@6b4cfc3708be — delivered since 2026-10-10T12:21:22Z
Delivery plan — builds messenger, telegram → novox; no bus step
tier 0: messenger, telegram
novox: receives messenger, telegram
Machines
messenger on novox: passed — healthy 3 times over 3m33s
telegram on novox: passed — judged with messenger: healthy 3 times over 3m33s
messenger on the rest running it: sent
telegram on the rest running it: sent
Transitions
2026-10-10 12:09 (new) → proposed (announced): novox/mesh-catalog#175's head announced
2026-10-10 12:11 proposed → checked (checked): the verdict names this commit
2026-10-10 12:11 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-10 12:15 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-10 12:15 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-10 12:21 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@6b4cfc3708be` — **delivered** since 2026-10-10T12:21:22Z
**Delivery plan** — builds messenger, telegram → novox; no bus step
- tier 0: messenger, telegram
- novox: receives messenger, telegram
**Machines**
- messenger on novox: passed — healthy 3 times over 3m33s
- telegram on novox: passed — judged with messenger: healthy 3 times over 3m33s
- messenger on the rest running it: sent
- telegram on the rest running it: sent
**Transitions**
- 2026-10-10 12:09 (new) → proposed (announced): novox/mesh-catalog#175's head announced
- 2026-10-10 12:11 proposed → checked (checked): the verdict names this commit
- 2026-10-10 12:11 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-10 12:15 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-10 12:15 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-10 12:21 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/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: 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 messenger, telegram → novox; no bus step
tier 0: messenger, telegram
novox: receives messenger, telegram
read by no module's build: modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go
Run by the build seat on novox as build-1791633619127705265 (builds --log build-1791633619127705265).
--- the gate: messenger, telegram
messenger: ok, 6 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, keeps state open, sent, asks, identities; 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: 1
2 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-10T11:55:18Z 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-10T11:55:18Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 2 module(s) in 1 tier(s): messenger, telegram
notes:
- modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go and modules/messenger/cmd/messenger/feedback_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 37459 strings of 637 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/paths 0.006s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 70, as kept
testing modules/messenger
ok messenger/cmd/messenger 1.856s
testing modules/telegram
ok telegram/cmd/telegram 1.050s
--- its merge-check-typescript.sh (typescript toolchain)
**Merge check** at `020c05fe`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: 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 messenger, telegram → novox; no bus step
- tier 0: messenger, telegram
- novox: receives messenger, telegram
- read by no module's build: modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go
Run by the build seat on novox as `build-1791633619127705265` (`builds --log build-1791633619127705265`).
```
--- the gate: messenger, telegram
messenger: ok, 6 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, keeps state open, sent, asks, identities; 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: 1
2 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-10T11:55:18Z 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-10T11:55:18Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 2 module(s) in 1 tier(s): messenger, telegram
notes:
- modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go and modules/messenger/cmd/messenger/feedback_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 37459 strings of 637 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/paths 0.006s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 70, as kept
testing modules/messenger
ok messenger/cmd/messenger 1.856s
testing modules/telegram
ok telegram/cmd/telegram 1.050s
--- its merge-check-typescript.sh (typescript toolchain)
```
The review found that a double tap while the phone's spinner turned would be
answered 'That answer was not taken', reading as if the approval failed; it is
now 'You already chose Approve at 13:30: recorded.' and does nothing more. The
fallback toast no longer promises a change that may not come (a stranger's
tap), the wait outlasts the router's 10 s wait for the controller's root word,
the channel's own refusals stay in the chat too, and the store's error words
stay in the journal.
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: 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 messenger, telegram → novox; no bus step
tier 0: messenger, telegram
novox: receives messenger, telegram
read by no module's build: modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go
Run by the build seat on g14 as build-1791633955867597629 (builds --log build-1791633955867597629).
--- the gate: messenger, telegram
messenger: ok, 6 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, keeps state open, sent, asks, identities; 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: 1
2 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-10T11:55:18Z 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-10T11:55:18Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 2 module(s) in 1 tier(s): messenger, telegram
notes:
- modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go and modules/messenger/cmd/messenger/feedback_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 37468 strings of 637 files
ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.009s
agent-home: no archive and no file written into under the agent's home
ok git.novox.be/novox/mesh-catalog/checks/paths 0.005s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 70, as kept
testing modules/messenger
ok messenger/cmd/messenger 1.979s
testing modules/telegram
ok telegram/cmd/telegram 1.041s
--- its merge-check-typescript.sh (typescript toolchain)
**Merge check** at `35c4de7d`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: 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 messenger, telegram → novox; no bus step
- tier 0: messenger, telegram
- novox: receives messenger, telegram
- read by no module's build: modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go
Run by the build seat on g14 as `build-1791633955867597629` (`builds --log build-1791633955867597629`).
```
--- the gate: messenger, telegram
messenger: ok, 6 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, keeps state open, sent, asks, identities; 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: 1
2 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-10T11:55:18Z 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-10T11:55:18Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 2 module(s) in 1 tier(s): messenger, telegram
notes:
- modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go and modules/messenger/cmd/messenger/feedback_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 37468 strings of 637 files
ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.009s
agent-home: no archive and no file written into under the agent's home
ok git.novox.be/novox/mesh-catalog/checks/paths 0.005s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 70, as kept
testing modules/messenger
ok messenger/cmd/messenger 1.979s
testing modules/telegram
ok telegram/cmd/telegram 1.041s
--- its merge-check-typescript.sh (typescript toolchain)
```
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: 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 messenger, telegram → novox; no bus step
tier 0: messenger, telegram
novox: receives messenger, telegram
read by no module's build: modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go
Run by the build seat on ace as build-1791634167610854180 (builds --log build-1791634167610854180).
--- the gate: messenger, telegram
messenger: ok, 6 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, keeps state open, sent, asks, identities; 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: 1
2 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-10T11:55:18Z 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-10T11:55:18Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 2 module(s) in 1 tier(s): messenger, telegram
notes:
- modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go and modules/messenger/cmd/messenger/feedback_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 37468 strings of 637 files
ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.010s
agent-home: no archive and no file written into under the agent's home
ok git.novox.be/novox/mesh-catalog/checks/paths 0.005s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 70, as kept
testing modules/messenger
ok messenger/cmd/messenger 1.661s
testing modules/telegram
ok telegram/cmd/telegram 1.043s
--- its merge-check-typescript.sh (typescript toolchain)
**Merge check** at `6b4cfc37`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: 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 messenger, telegram → novox; no bus step
- tier 0: messenger, telegram
- novox: receives messenger, telegram
- read by no module's build: modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go, modules/messenger/cmd/messenger/feedback_test.go
Run by the build seat on ace as `build-1791634167610854180` (`builds --log build-1791634167610854180`).
```
--- the gate: messenger, telegram
messenger: ok, 6 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, keeps state open, sent, asks, identities; 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: 1
2 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-10T11:55:18Z 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-10T11:55:18Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 2 module(s) in 1 tier(s): messenger, telegram
notes:
- modules/messenger/README.md, modules/messenger/cmd/messenger/answers_test.go and modules/messenger/cmd/messenger/feedback_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 37468 strings of 637 files
ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.010s
agent-home: no archive and no file written into under the agent's home
ok git.novox.be/novox/mesh-catalog/checks/paths 0.005s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 70, as kept
testing modules/messenger
ok messenger/cmd/messenger 1.661s
testing modules/telegram
ok telegram/cmd/telegram 1.043s
--- its merge-check-typescript.sh (typescript toolchain)
```
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Issue 372 (tapping Approve or Decline on Telegram gives the operator no visible feedback).
What happened at 13:30 on 2026-10-10 (messenger journal,
operator-channel.history,telegram.telegram_status): the two questions were sent at 13:25:33. Two taps at 13:30:34 and 13:30:36 were refused ("it belongs to no open message"): their tickets were held by no open message, so they were on older messages; a "That answer was not taken" message went to the chat for each. The Approve taps at 13:30:51 and 13:30:58 were recorded as warrants, and each question was edited (history:edited, telegramlast_delivered13:30:58, no failure logged). But the channel had acknowledged each tap at once with no text (answerTap(cb.ID, ""), before the router judged anything), so no toast; and the edit kept the question's title, removed the buttons and only added "Approve: chosen at 13:30 on Telegram" as the first body line. An edit rings nothing. So the operator saw no confirmation and only a subtle change.The fix
answerCallbackQuerywaits for the router's reply to that tap and shows it as the toast (title and first body line, cut at 200 characters). A reply of one line is only the toast; one with a body (a refusal's reason, Details) is also sent to the chat. Without a reply in 8 seconds, the toast claims nothing ("Passed to the mesh, which has not decided yet…") and the late reply goes to the chat; a reply Telegram no longer takes as the acknowledgement also goes to the chat. A secret reply is never a toast. A tap that cannot be said to the router is acknowledged with "…Nothing was done."decidedfrom router to asker). So the router says only what it knows: whether the asker was told. No second edit is made.Reviewers' checklist
confirmruns insidecloseAskonly afterUpdateAsksucceeded;TestTheConfirmationNeverClaimsWhatDidNotHappen(store refuses the write: only the refusal, with "could not be recorded"; bus refuses the warrant: "is told as soon as the bus takes it"). Telegram never acknowledges before the router's word (TestATapIsAcknowledgedWithTheRoutersWordOnIt).TestARefusedTapSaysWhyOnThePhoneAndInTheChat,TestARefusedAnswerSaysWhyInReplyToTheTap.answerCallbackQuery, not an edit; a tap is acknowledged once (settleTapdeletes under the lock; the timer after a reply does nothing). Order checked: confirmation, then the edit (TestAnApprovalIsConfirmedWhereItWasGivenAndThenTheQuestionSaysHowItEnded).go test -racepasses for both modules; the words check passes. Do not merge without review.Delivery
novox/mesh-catalog@6b4cfc3708be— delivered since 2026-10-10T12:21:22ZDelivery plan — builds messenger, telegram → novox; no bus step
Machines
Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Merge check at
020c05femesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: 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 messenger, telegram → novox; no bus step
Run by the build seat on novox as
build-1791633619127705265(builds --log build-1791633619127705265).Merge check at
35c4de7dmesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: 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 messenger, telegram → novox; no bus step
Run by the build seat on g14 as
build-1791633955867597629(builds --log build-1791633955867597629).Merge check at
6b4cfc37mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: 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 messenger, telegram → novox; no bus step
Run by the build seat on ace as
build-1791634167610854180(builds --log build-1791634167610854180).