fleetd #421: a lead can read its own held peer mail

Features entry for fleet_poll{coordId} — primary-only, non-destructive,
full bodies. Records why READ was not reused (the roster-carries-no-secrets
grant does not cover a lead-to-lead body) and the mailbox.pending: 0 trap.

Also re-syncs the portable CLAUDE.md block template with the repo's copy:
the #421 work added an intent->tool row for reading held peer mail, and a
worker cannot commit this submodule.
Dai Ha
2026-09-10 14:09:33 +07:00
parent 01a7cd6848
commit 4a297bda8c
2 changed files with 30 additions and 0 deletions
+29
@@ -51,6 +51,7 @@ six weeks, and the table alone will not carry it.
| [Durable reply inbox](#durable-reply-inbox) | `broker:` | CB-307 | `msg/AmqpReplyInbox` |
| [Set a member's auto-compact window](#set-a-members-auto-compact-window) | per-profile `autoCompactWindow:` | CB-636 | `member/ClaudeCodeLauncher`, `member/OpenCodeLauncher` |
| [Leads on different hosts talk over a shared broker](#leads-on-different-hosts-talk-over-a-shared-broker) | `coordinator:` | CB-637 | `msg/LeadMailbox`, `msg/LeadCoordLoop` |
| [A lead can read its own held peer mail](#a-lead-can-read-its-own-held-peer-mail) | `coordinator:` | #421 | `mcp/FleetMcp`, `auth/Authz` |
| [Draining an inbox is lead-only, on both entry paths](#draining-an-inbox-is-lead-only-on-both-entry-paths) | (always on, with `auth:`) | #272 | `mcp/FleetMcp.pollAction` |
| [Broker password out of the config](#broker-password-out-of-the-config) | `broker.uriEnv:` | CB-635 | `config/FleetConfig` |
| [An unreachable broker does not stop the daemon](#an-unreachable-broker-does-not-stop-the-daemon) | (always on) | CB-635 | `Fleetd.selectReplyInbox` |
@@ -2324,6 +2325,34 @@ coord-id it was already told.
---
## A lead can read its own held peer mail
**What.** `fleet_poll{coordId: <your own coord-id>}` returns this daemon's held lead-to-lead
messages in full, and does not ack them. The messages stay held, so reading twice returns the same
bodies. It reads only *your own* mailbox: passing a peer's coord-id is refused with a message saying
so, because no route exists for reading another daemon's mail.
**On.** Nothing to configure beyond the `coordinator:` block that lead-to-lead messaging already
needs. Pass your own `selfId` — `fleet_list` reports it as `coordinator.selfId` — as `fleet_poll`'s
`coordId`. `fleet_list` also now reports `heldCount` and `heldDurable` beside `held[]`.
**Why.** A lead could see *that* it had peer mail but not read it. `fleet_list`'s `held[]` carries
only an 80-character preview, on purpose, so a constantly-called roster scan never dumps a
coordination body. `fleet_poll{target}` drained the wrong store — a worker's reply inbox, not the
coordinator mailbox — and returned an empty list with no error. The only other route, `fleet_ack`,
would have destroyed the message before anyone read it. So the full body was reachable in principle
and unreachable in practice, and the busiest leads were the ones most affected: delivery into a
lead's pane is status-gated, so a lead that never goes idle never drains its own mailbox.
**Gotcha.** This is **primary-only**, under a new authorization action `COORD_READ`. That includes
refusing an architect, which holds the ordinary `READ` action today. The reason is that `READ`'s
grant rests on the roster carrying no secrets, and a lead-to-lead body is not the roster — it is
where leads discuss host shapes, credential states and unmerged work. Also do not read
`mailbox.pending: 0` as an empty mailbox: `pending` counts only broker-ready messages, so a healthy
mailbox holding real mail reports zero. `heldCount` is the honest number.
---
## Fleet health can finally reach its fault states
**What.** `FleetHealthMonitor` ticks on its own timer, well away from the 250ms delivery poller. Each
+1
@@ -443,6 +443,7 @@ the merge — and merging on a reviewer's word is delegating it by proxy.
| Message a **peer lead** on this host | `fleet_send{sessionId: <their terminal>, content}` — `fleet_list` → `leads` reports it. Coordination only, **never** a task |
| Message a **peer lead** on another daemon or host | `fleet_send{coordId: <their coord-id>, content}` — needs a `coordinator:` block; your own coord-id is in `fleet_list`. Coordination only, **never** a task |
| Answer a peer lead that messaged you | `fleet_send{coordId}` — or `{sessionId}` if they are on this host. **Not** `fleet_reply`: it has no peer route and the publish is refused |
| Read your own held lead-to-lead mail (no ack) | `fleet_poll{coordId: <your own coord-id, from fleet_list's coordinator.selfId>}` — primary-only; never acks, so `fleet_list`'s `held[]` still shows it after. `fleet_list`'s `held[]` gives only a truncated preview — this is the only way to read the full body |
| Collect a held reply | `fleet_poll{target}` · then `fleet_ack{target, msgId}` |
| Tear down a member | `fleet_stop{paneId}` |