acpmux: autoResumeDelaysMs sets the retry loop's attempts, not only its waits
Lawrence via Leo, 2026-10-28, word for word: "should have retry button + configurabl etimer loop retry".
acpmux already runs the timed loop: a turn a connection or capacity error cut off is continued by itself after autoResumeDelaysMs (hub/auto_resume.rs), default [10000, 60000, 300000, 1200000], [] off. The waits are configurable. The attempts are not, and that is this PR.
MAX_ATTEMPTS was one constant doing two jobs:
- the ceiling on the configured list —
checked_delaystruncated it to four entries, so a timed retry loop longer than the default could not be configured at all even though the key reads free-form; - the cap on a chain of daemon-restart continuations —
log_restart_continuationcompared against the constant, not against the list, soautoResumeDelaysMs: [10000]("retry once") still allowed four restart continuations.
Both numbers being four is what hid the second one: a configured list was truncated before it could disagree with the constant. Lift the ceiling and the latent bug becomes a live one, so both are fixed together, test first.
What changes
MAX_CONFIGURED_ATTEMPTS(12) is the ceiling on the configured list. The default stays four waits spanning about 26 minutes, and the per-entry 1 s to 1 h bound is unchanged; the warning text follows the new ceiling.configured_attempts()reads the attempts from the configured list: its length, the default's four when the key is unset, none for[].log_restart_continuationreads that instead of the constant, so a restart chain gives up after the attempts the config asked for, exactly as a transport cut already did.[]still turns it off, and a contended config lock still reads as the default waits, never as off.- Doc comments and the acpmux README now say the key is the whole loop, not only its waits.
Deliberately not in scope: no new UI, no new transport, no new setting surface, no change to the default waits or to which errors are transient. This is the configurable half of the clause only; the Retry button half is #25947, which is someone else's open PR and is untouched here.
Tests
Focused command, both runs scripts/ci/cmux-tui-focused-test.sh auto_resume through cmux-tui.yml in focused mode:
- Red on the test-only commit
a9a6376662603601574c1cd8f83f906ab37b67c0: run 40773673821. That commit adds the tests against unchanged product source, so the two failures are the two defects above. - Green at this head
62fde3f15c455b01137982c71a2da7057374210e: run 40773423237.
New tests:
hub::auto_resume::restart_resume::tests::the_configured_waits_set_how_many_restart_continuations_run— one wait runs one continuation and then gives up withauto_resume_exhausted; six waits run all six.hub::auto_resume::restart_resume::tests::an_unset_key_keeps_the_default_attempts_and_an_empty_list_turns_it_off— the unset key keeps four, and[]logs nothing because off is not a chain that ran out.hub::auto_resume::tests::the_configured_waits_say_how_many_attempts_run—configured_attemptsand the ceiling, with the default asserted to stay under it.hub::auto_resume::tests::configured_waits_are_checked— a 5- and a 12-entry list are kept whole.
Observed / Not run
- Observed: the focused Rust runs above. No Swift source changed and no app compile is involved.
- Not run: no capture. This changes no UI — acpmux is the daemon, and the only user-visible text is a
tracing::warn!for a refused config. No webview, no native source.
Changelog
Fixed: autoResumeDelaysMs sets how many automatic retries a cut turn gets, not only how long it waits between them, and a loop longer than the default can be configured.
Agent session: agent session