From d45ed67ca7fe926fd3486e8d50f921c0f236ce6f Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Sun, 11 Oct 2026 18:38:56 -0500 Subject: [PATCH] plans: bus stranded-delivery brief from row 59 review (Note B) Darkwing's row 59 review (comment 27487) found that a message delivered to a run that releases the role unread can't be received or read by the next holder. Sage's ruling: keep at-most-once delivery, as the bus README promises, and list stranded messages in the agents read so a person decides whether to resend. Owner Darkwing after row 59, reviewer Filbert, held behind the cutover with the other bus rows (decision 94). Co-Authored-By: Claude Opus 5.5 --- .../plans/2026-10-11_bus-stranded-delivery.md | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 docs/plans/2026-10-11_bus-stranded-delivery.md diff --git a/docs/plans/2026-10-11_bus-stranded-delivery.md b/docs/plans/2026-10-11_bus-stranded-delivery.md new file mode 100644 index 000000000..4b063fc49 --- /dev/null +++ b/docs/plans/2026-10-11_bus-stranded-delivery.md @@ -0,0 +1,78 @@ +# Bus: a message delivered to a run that left is stranded (2026-10-11) + +Status: written by Sage, lead. It follows `docs/plans/BRIEF-TEMPLATE.md`. +From Darkwing's row 59 review (comment 27487 on #1548, Note B). The gap +predates row 59. The row waits until after the dogfood cutover, like the +other bus rows (lead decision 94). + +## Show messages stranded by a holder change + +### Problem + +`packages/bus/src/broker.mjs` keeps a message's delivery history in the +`deliveries` table. Three places read it: + +- `message.receive` (line 753) returns only messages with no `delivered` + or `read` row. +- `#routeWaiting` (line 892), run when a new holder claims the role, + routes only messages with no `delivered` or `read` row. +- `message.read` (line 784) refuses `not-recipient` unless the latest + `delivered` row names the caller's run. + +So when a holder receives a message and releases the role without +reading it, the next holder can't receive it, can't read it, and nothing +points at it. Row 59's agent-state read reports the new holder as idle, +which is correct (its test 5 pins that), but the message sits unanswered. +Sage checked the three queries against the code on 2026-10-11. + +Redelivery is not the fix. The bus README says a delivery the broker +can't confirm is never replayed to a new holder, and that holds here: the +old run may have acted on the message without marking it read, so a +replay can do the work twice. Sage's ruling: keep at-most-once delivery +and make a stranded message visible, so a person decides whether to send +it again. + +### Owner and reviewer + +Owner: Darkwing, after row 59. Reviewer: Filbert. + +### Files owned + +- `packages/bus/src/broker.mjs`, the read that row 59's agent state uses + only +- `packages/bus/src/views.mjs`, if the agents view passes the field + through +- `packages/bus/tests/` +- `packages/bus/README.md`, the delivery paragraph and the agents read + only +- `agents/darkwing/work/queue-/` + +### What ships + +- A stranded message is one addressed to a role, with a `delivered` row + whose run no longer holds that role, and no `read` row. +- The agents read gives each role a `stranded` list: message id, from, + the run it went to and when, oldest first, at most 50. An empty list + when there are none. +- No message is redelivered, re-routed or marked read by this row, and + no delivery row is written or changed. +- The README's delivery paragraph says what a release without a read + leaves behind and where to see it. +- Tests: deliver, release unread, claim by a new run, and the message is + listed for the role; the same after a read is not listed; a message + delivered to the current holder and unread is not listed; the list cap + and order; the agents read for a role with none. +- The packet names what the Console would need to show the list. That is + a follow-up row, not this one. + +### Out of scope + +Redelivery, any new write verb, the human transport, the `deliveries` +schema and any Console change. If row 59 lands with a shape this can't +extend without breaking its tests, stop and tell Sage. + +### Gate + +Filbert approves on the row's issue naming the candidate manifest. The +bus, webui, control-board and cli node suites and every +`scripts/test-*.sh` green on Sage's gate rerun.