acpmux: preserve pending prompt identities under queue pressure
When more than 64 prompts are running or queued in one session, acpmux can evict an unfinished prompt's retry identity. Retrying that prompt can execute it again or report that its live turn was interrupted. Keep every pending identity, including restored queue entries, and retain at most 64 completed outcomes after settlement or withdrawal.
Protocol regressions cover both retry modes under 65 queued prompts and restored-queue withdrawal. A settlement test checks that completed history returns to its bound as pending work drains. The durable replay lookup moves beside the ledger logic to keep the turn handler below its file-size ratchet.
Adopted from a finished lane on 2026-10-21. Merged feat-cmux-next at 9aa00c6e20f1. One conflict, in hub/turns.rs: base now calls prompt_unless_held where this branch called run_prompt. The resolution keeps base's call and this branch's ledger lock and prune after the turn settles. Base still evicts pending identities past 64 (PROMPT_LEDGER + pop_front in turns.rs and queue.rs), so the fix is still needed.
Validation
All runs were fleet steps (cmux-ci run --class isolated --script scripts/ci/cmux-tui-rust-check.sh --arg test --arg prompt_ledger --ref SHA). None ran on a developer Mac.
- Green, head bdb324a4cf60 (step 7a75aaf90ac099af7a065c17): 6/6 pass. These are the unit test
hub::prompt_ledger::tests::prompt_ledger_keeps_pending_and_bounds_completed_outcomes_as_they_settleand the integration testsprompt_ledger_keeps_live_pending_identity_{with,without}_resend,prompt_ledger_keeps_recovered_pending_identity_until_withdrawn,prompt_ledger_pins_withdrawal_until_its_log_append_finishesandprompt_ledger_failed_withdrawal_append_remains_best_effort. - Red, test-only commit 4c2db6695c90 (step 87098f37671743342143de6c, the fix not yet applied): 3/3 fail.
..._without_resend: "retry acquired another queue entry" (position: 66)...._with_resend: fails at the same assertion...._recovered_pending_identity_until_withdrawn: answersstatus: interruptedinstead ofwithdrawn.
- Red, withdrawal test commit 466b28026bb2 (step c5d30f9a8afff62f4b5c758c, first fix applied, append pin not yet): 5 pass and 1 fails.
prompt_ledger_pins_withdrawal_until_its_log_append_finishesreports "retry escaped the in-progress withdrawal append" (status: interrupted). - PR CI at bdb324a4cf60:
cmux-next fast tier (cargo),cmux-tui spec inventory / rustfmtand allcmux-tui artifactsbuilds, including acpmux on x86_64-pc-windows-gnu, are green.- The one red,
cmux-next checks→ Tier routing (tests/test_cmux_next_route.py), is a base finding.Packages/macOS/CmuxNext/Tests/CmuxNextHomeEngineTestswas added on base (657389dbb3d2 and earlier) without a target-graph entry. This PR changes no file outsidecmux-tui/crates/acpmux.
- The one red,
python3 scripts/cmux-next/prepush-gate.py: no new violations.
Observed / Not run
- Observed: the fleet red and green runs above, the PR CI results above and the pre-push gate.
- Not run: workspace clippy did not reach acpmux. The fleet
clippystep (2849e118400882038cbda510) stopped at a baseclippy::unnecessary_sort_byerror incrates/cmux-worktree-care/src/store.rs:97, a crate this PR does not touch. - Not run: the red runs use the branch's own historical test-only commits, which sit on an older base (10-16). The ledger code they exercise is unchanged on today's base.
- Not run: isolated CLI dogfood. No native app build was run.
Changelog
Fixed: Pending agent prompts retain their retry identity under queue pressure and after queue restoration.
Agent session: cosmic-gray
🤖 Generated with Claude Code