acpmux: preserve pending prompt identities under queue pressure

Merged
TE
16d ago
+418-76

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_settle and the integration tests prompt_ledger_keeps_live_pending_identity_{with,without}_resend, prompt_ledger_keeps_recovered_pending_identity_until_withdrawn, prompt_ledger_pins_withdrawal_until_its_log_append_finishes and prompt_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: answers status: interrupted instead of withdrawn.
  • 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_finishes reports "retry escaped the in-progress withdrawal append" (status: interrupted).
  • PR CI at bdb324a4cf60: cmux-next fast tier (cargo), cmux-tui spec inventory / rustfmt and all cmux-tui artifacts builds, 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/CmuxNextHomeEngineTests was added on base (657389dbb3d2 and earlier) without a target-graph entry. This PR changes no file outside cmux-tui/crates/acpmux.
  • 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 clippy step (2849e118400882038cbda510) stopped at a base clippy::unnecessary_sort_by error in crates/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