fix: summarization retries panicked in debug, and a test relied on it - #156
Merged
Conversation
Found by the test-coverage review, outside the question it was asked. RetryConfig::delay_for_attempt documents a 1-indexed attempt and computes `attempt - 1`. llm_compaction.rs passed the raw `0..=max_retries` loop variable, so the first retry underflowed usize and panicked in debug. agent_loop.rs increments before calling and was correct; this was confined to compaction. The code even wrote `attempt + 1` for its own log message, so the 0-indexing was known locally and lost at the call. The panic landed on a detached task, so nothing surfaced: the summarization vanished, no briefing arrived, and compaction fell back deterministically — one of the behaviours #150 is about. delay_for_attempt now saturates, so missing the contract costs the backoff, not the task. provider_failure_falls_back_deterministically was passing *because* of the panic. FailingProvider returns a retryable error; the instant death released the in-flight slot well inside the test's 100ms window. With retries working the first backoff is ~1s and the slot is legitimately still held, so the test now configures no retries — it is about the drop guard, not backoff timing. Also closes the coverage hole the review found and I had missed: deleting the only warn_losing_race_once call site in compact() disconnected the whole feature — the counter would never move for any real user — and every test stayed green, because they all call the function directly. compact_counts_real_fallbacks_and_warns_on_the_streak drives the real path; deleting the call site now fails it. I briefly believed that mutation was already caught. It was not — the suite was red at the time from the retry fix above, and I misread a pre-existing failure as a catch. Re-checked against a green baseline. 627 passed, clippy clean under -Dwarnings. Refs #150 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found by the test-coverage review of #155, outside the question it was asked.
The bug
RetryConfig::delay_for_attemptdocuments a 1-indexed attempt and computesattempt - 1.llm_compaction.rspassed the raw0..=max_retriesloop variable, so the first retry underflowedusizeand panicked in debug builds.agent_loop.rsincrements before calling and was correct — this was confined to compaction.The code even writes
attempt + 1for its own log message a few lines above, so the 0-indexing was known locally and lost at the call.It landed on a detached task, so nothing surfaced. The summarization simply vanished, no briefing arrived, and compaction fell back deterministically — which is one of the behaviours #150 was filed about. Verified directly:
delay_for_attemptnow usessaturating_sub, so a caller that misses the 1-indexed contract loses the backoff rather than the task. Both call sites are corrected to passattempt + 1.A test was passing because of the panic
provider_failure_falls_back_deterministicallyasserts that a failed request leaves the in-flight slot idle, and checks after 100ms. ItsFailingProviderreturns a retryable error — so the instant panic-death released the slot well inside that window.With retries actually working, the first backoff is ~1s and the slot is legitimately still held, so the test failed. It now configures
RetryConfig::none(): it is about the drop guard, not about backoff timing. The reason is written into the test so it isn't "fixed" back later.Coverage hole from #155 that I had missed
Deleting the only
warn_losing_race_once()call site incompact()disconnects the entire feature — the counter never moves for any real user — and every test stayed green, because they all call the function directly.compact_counts_real_fallbacks_and_warns_on_the_streaknow drives the real path throughcompact(); deleting the call site fails it.I should flag that I briefly reported this mutation as already caught. It wasn't — the suite was red at the time from the retry fix above, and I read a pre-existing failure as a catch. Re-verified against a green baseline before and after.
Verification
(attempt - 1)attempt to subtract with overflowwarn_losing_race_once()call siteeach deterministic compaction must advance the streakmust advance the streak, not clear itcargo test --all-features: 627 passed, 0 failed. Clippy clean under-Dwarnings.🤖 Generated with Claude Code