Skip to content

send queue: list only pending messages; tap a message to see all of it - #391

Merged
ZacxDev merged 2 commits into
mainfrom
fix/send-queue-hide-finished
Nov 1, 2026
Merged

ZacxDev merged 2 commits into
mainfrom
fix/send-queue-hide-finished

Conversation

@ZacxDev

@ZacxDev ZacxDev commented Nov 1, 2026

Copy link
Copy Markdown
Owner

What

Two changes to the send queue in a mirrored window's Rendered view:

  1. Only pending messages are listed. Sent and cancelled messages leave the list at once, so there is no backlog to Delete by hand. A failed message stays until you Retry or Delete it, so a failure never disappears unseen. A failure that was already retried is hidden, because its retry row carries it. (This was the operator's choice: "Keep failed until handled".)
  2. Tap a message to see all of it. The preview is cut at 200 bytes and clamped to two lines. It is now a button that opens a popover with the whole text and a Close.

How

  • sendqueue.PGStore.List: the open rows (queued, sending), plus state = 'failed' AND retried_as IS NULL, newest first, capped at FailedShown. HistoryShown (5) is replaced by FailedShown, which equals MaxOpenPerTarget (20), so a whole queue that failed is shown in full. The Delete route is unchanged and still deletes any finished message.
  • ui.sendQueuePreview: a popovertarget button (44px tall, aria-label "Show the whole message: …", Enter and Space work natively) and a top-layer popover (role=dialog) holding the body and a Close button. It works without script and causes no layout shift.
  • The list's poll (menuOpen) now checks every [popover] in the list, not just the row menus and the waiting line. Before this, a poll redraw would have closed an open message.
  • sendQueueListView now puts the whole Body on every listed row. Before, only queued rows had it. Failed rows get it too: they are the caller's own text under row-level security, and their preview is cut the same way.
  • docs/sending-and-step-up.md is updated to match.

Tests

test origin/main code this branch
sendqueue TestListShowsOnlyWhatStillNeedsSomething (queued, sending, sent, cancelled, failed ×2, failed and retried, plus another owner's and another window's failures) red green
sendqueue TestListBoundsTheFailures red (6 rows, want 21) green
sendqueue TestRetryQueuesAFailedMessageAgainOnce (updated) red green
ui TestATapOnAPreviewOpensTheWholeMessage red (no #mv-qf-41) green
ui TestThePollDoesNotRedrawUnderAnOpenWholeMessage red green
api TestEveryListedRowCarriesItsWholeText red (with only the API change reverted, the sending row has no popover) green
api TestTheListDrawsDeleteOnAnUnhandledFailureOnly (PG) red (handled row drawn) green
e2e a tap on a long queued message shows the whole of it… red (no opener) green

For the red runs, origin/main's store.go / ui/send_queue.go / api/send_queue.go were checked out. A temporary shim declared the new constant names so the tests would compile. TestDeleteIsDrawnOnAFailedRowOnly (memQueue) checks that the fake matches the real store's filter and that the view maps rows correctly. It does not catch this regression on its own.

Mutation test: putting back the poll's old popover selector turns the e2e red, at still open after a poll.

Results:

  • go test ./internal/sendqueue/ ./internal/api/ ./internal/ui/ with a database (MUSTER_TEST_REQUIRE_DB=1): 3344 PASS, 0 FAIL, 0 SKIP.
  • go vet ./... is clean, and make css-check matches.
  • e2e send-queue.spec.ts: 41/41 passed.
  • e2e attention, composer-menu, cls, mirror-ask: 57/57 passed.

🤖 Generated with Claude Code

@ZacxDev

ZacxDev commented Nov 1, 2026

Copy link
Copy Markdown
Owner Author

Round 0 (requirements & deletion): proceed to the checklist. Ledger: requirements 7 (unattributed 2: the failed-row cap of 20, and the whole-message popover widened to sending/failed rows) · deletion candidates 2 · no open premises.

D1 — queued rows now carry the whole message twice (the new popover and the Copy template); Copy could read the popover's text and the template could go
D2 — the Delete route still accepts sent/cancelled messages and Deletable is still "finished", though the list can no longer draw either; could narrow to failed (lean: keep, harmless for pages drawn before the deploy)

@ZacxDev

ZacxDev commented Nov 1, 2026

Copy link
Copy Markdown
Owner Author

Round 1 (nine-axis checklist): 0 🔴, 2 🟡, 3 🟢. No 🔴, so the ladder ends; the 🟡s are fixed un-re-audited.

pr: ZacxDev/muster#391
round: 1
head: 00b53010b96131236f210b1771f221781a5433aa
base: 0b2daef73506c6175cb4826c8711b190ca0214e8
red: 0
yellow: 2
green: 3
findings:
  - Y1 payload internal/sendqueue/store.go:423 + internal/api/send_queue.go:554 — routed/chief-nudge failures (no Retry, retried_as never set) persist until manual Delete
  - Y2 scaffolding internal/sendqueue/store_list_pg_test.go:96-111 — FailedShown value unpinned; mutant FailedShown=5 survives
  - G3 scaffolding internal/ui/send_queue_full_test.go:127-137 — spelled guard; menuOpen-never mutant survives (e2e covers it)
  - G4 payload docs/sending-and-step-up.md — "never disappears unseen" overstated vs the 7-day prune and the 20 cap
  - G5 payload internal/api/send_queue.go:398 — full body on every row, doubled on queued rows
stop: ladder ends (no red)

ZacxDev and others added 2 commits November 1, 2026 09:48
…t on tap

The Rendered view's queue listed the five most recently finished messages
beside the open ones, so sent and cancelled messages piled up and each had
to be deleted by hand. PGStore.List now returns the open rows (queued,
sending) and the failed rows not yet retried, bounded by FailedShown (the
open bound, 20). A sent or cancelled message leaves the list at once; a
failure stays until it is retried or deleted, so it never vanishes unseen;
a failure already retried is hidden, since its retry row carries it. The
Delete route still deletes any finished message.

A row's preview is cut at 200 bytes and clamped to two lines. It is now a
button (popovertarget, 44px, aria-label) opening a top-layer popover with
the whole text and a Close, so it works without script and moves nothing.
Every listed row, failed ones included, now carries its whole text. The
list's poll skips a redraw while ANY popover in the list is open, so it does
not redraw an open message away.

Tests: internal/sendqueue TestListShowsOnlyWhatStillNeedsSomething and
TestListBoundsTheFailures (red against origin/main's store.go); the UI's
TestATapOnAPreviewOpensTheWholeMessage and the API's
TestEveryListedRowCarriesItsWholeText (red against origin/main's
ui/send_queue.go and api/send_queue.go); existing tests and e2e specs that
waited for a sent or cancelled row now wait for the row to leave the list.
A new send-queue e2e taps a long queued message, sees its tail, checks no
layout shift and that it stays open across a poll (red on origin/main; red
with the poll's old popover selector).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Audit round 1 on #391:

- Y1: a failed routed message (route_id) or chief nudge (chief_nudge_id)
  has no Retry and its outcome goes back to the chief, so under the new
  filter it sat in the list until deleted by hand. List now leaves both out
  (both columns are NULL on a person's own row); the in-memory fake in
  internal/api matches. TestListLeavesOutAFailureHandedBackToTheChief: red
  before the filter change, green after. The e2e specs that made a failure
  with sqfix 'route' to exercise Delete now use an expired message (a
  person's own failure); the routed one now asserts it leaves the list.
- Y2: TestFailedShownCoversAWholeQueue pins FailedShown >= MaxOpenPerTarget
  (20), and TestListBoundsTheFailures expects a literal 21 rows. The
  FailedShown=5 mutant is red in both.
- G4: the docs and the store comment no longer say a failure "never
  disappears": it is listed until retried, deleted, or pruned 7 days after
  it failed, only the newest 20, and routed/nudge failures not at all.
- G5: Copy message reads the row's popover text; the duplicate template
  is gone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ZacxDev
ZacxDev force-pushed the fix/send-queue-hide-finished branch from 00b5301 to 870d185 Compare November 1, 2026 16:00
@ZacxDev
ZacxDev marked this pull request as ready for review November 1, 2026 16:27
@ZacxDev
ZacxDev merged commit b60d5d9 into main Nov 1, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant