From 9d566cfb2e042f23b95e6d32b7717267bef70d08 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Tue, 4 Aug 2026 07:49:36 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=9F=20fix:=20Address=20Codex=20Round?= =?UTF-8?q?=2012=20On=20The=20Queued=20Outbox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four P2 findings, all valid. A recovered row now leaves the queue for its cancellation round trip. It stayed put through that await, so a run completing mid-flight could drain and send the very message being removed — the hazard clear-all already avoided by reserving up front. Refused cancellation returns the row to its original slot untouched; a settled one returns it already downgraded, which retires `downgradeQueuedRecovery` and keeps the public contract unchanged. Clear all takes the empty-edit standdown. I had argued this one as a deliberate exception, since its payload lands in the composer where a reappearing word is visible rather than silently sent. Codex pressed, and uniformity across every reader of the queue is easier to reason about than an exception worth remembering. The expanded rows scroll. The composer box is `overflow-hidden`, so a deep queue clipped rows with no way to reach them; the cap is on the ROWS alone, leaving the disclosure and the actions outside it. The scroll container is named by its own count rather than repeating the outer stack's label, which would have nested two identically named lists. An already-cancelled tombstone survives a second queue action. Retiring twice turned it back to null and exposed the parked epoch it existed to neutralize. --- .../components/Chat/Input/QueuedOutbox.tsx | 17 +++- .../__tests__/PendingSteerChips.test.tsx | 40 ++++++++ .../hooks/Chat/__tests__/useSteering.spec.tsx | 97 +++++++++++++++++++ client/src/hooks/Chat/useSteering.ts | 81 ++++++++-------- 4 files changed, 192 insertions(+), 43 deletions(-) diff --git a/client/src/components/Chat/Input/QueuedOutbox.tsx b/client/src/components/Chat/Input/QueuedOutbox.tsx index 5af6b61880..d6067db949 100644 --- a/client/src/components/Chat/Input/QueuedOutbox.tsx +++ b/client/src/components/Chat/Input/QueuedOutbox.tsx @@ -467,6 +467,10 @@ function QueuedOutboxBase({ } return emptyEditId != null ? localize('com_ui_queue_edit_empty') : undefined; })(); + /** Clear all folds the queue the same way Merge does, so an unresolved empty + * edit would hand words the user deleted back to the composer. Uniform with + * every other reader rather than an exception worth remembering. */ + const clearBlockedReason = emptyEditId != null ? localize('com_ui_queue_edit_empty') : undefined; /** The shortcut's promise is the NEWEST waiting message, which is not the * last array slot once a promotion has reordered the queue — so pick by * stamp. Recovery-bound rows are skipped because steering refuses them @@ -572,8 +576,15 @@ function QueuedOutboxBase({ {expanded && (
{queued.map((message, position) => (