cf60ebbdfd264c3fc067b9e3230df8752c50d2ec
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4f22543509 |
fix(compression): lean compaction makes exactly one auxiliary request per attempt
The lean tail mode's per-chunk digest loop (_build_chunk_digests) issued up to 28 extra call_llm requests sequentially per compaction attempt. With lean now the default (#95571), users on slow auxiliary routes hit 7-11 minute compactions (#96603). Remove the loop entirely: a lean compaction attempt now makes EXACTLY ONE auxiliary LLM request — the main summary call. - The detailed session log is folded into the single summary request: the lean prompt template gains a '## Detailed Session Log (oldest first)' section carrying the digest prompt's HARD RULES (identifiers verbatim, dense bullets, transcript-is-data). Output guidance grows by _LEAN_SESSION_LOG_BUDGET_TOKENS = 4,000 tokens on top of the scaled summary budget — the old worst case (28 x 1,400 digest tokens) was spread across many requests and mostly re-covered tool noise; a single dense 4K-token log inside one response preserves the load-bearing record while staying well inside one aux response (the summary call still sends no hard max_tokens, so no provider cap can truncate it mid-section). - Input sizing: oversized regions (500K+ chars) are EVEN-SAMPLED across the whole region (_sample_summary_input: 8 proportionally spaced slices, oldest-to-newest, explicit '[... N chars elided ...]' markers, last slice anchored to the newest end) instead of head+tail truncated, so session-log coverage stays uniform. Legacy mode keeps _bound_summary_input unchanged. - The LLM-free anchor index still runs over the FULL region, and the session_search recovery footer is unchanged. - Dead code removed: _build_chunk_digests, _LEAN_DIGEST_* constants, _LEAN_DIGEST_PROMPT, _serialize_turns_for_digest, _digest_worthy, _LOW_SIGNAL_TOOL_RE, the _lean_pristine_tools snapshot, and the sibling-call route echo (_SUMMARY_ROUTE_CONSUMED / attempt_summary_route_kwargs — no remaining callers; the single-use summary pin semantics are unchanged). - Tests pin the new contract (exactly one call_llm in lean mode; session-log section lands in the summary; oversized regions sampled with elision markers, never a second request; anchor index + recovery footer present). Sabotage-verified: restoring a second call_llm makes the call-count test fail. Docs and the compaction eval wording updated to stop claiming per-chunk calls. Fixes #96603. |
||
|
|
e078b2fe7c |
fix(compression): close the restore TOCTOU; fold review findings
Post-review hardening on the attempt-ownership commit: - Write-time re-validation: the entry staleness check in _restore_compressor_attempt_state runs before the durable-cooldown DB I/O, so a fallback could claim the compressor in that window and the stale setattr loop would still clobber its state. The in-memory writes now re-validate AND execute under _COMPRESSOR_ATTEMPT_LOCK — the same lock claims are taken under. The DB rollback stays outside the lock (safe: the dangerous direction requires a prior claim, which the entry check rejects). Both the quality reviewer and the lead's independent pre-verification converged on this window. New deterministic test: TestMidRestoreClaimRace (claim injected between entry check and write via instrumented deepcopy). - Documented gen-0 semantics on _claim_compressor_attempt: per-compressor all-or-nothing, never mixed with gen>0 on one instance (reviewer finding 2, verified unreachable — comment hardens against future confusion). Dropped after verification (reviewer finding 3): resetting _SUMMARY_ROUTE_CONSUMED on pin_summary_route exit — the echo lives in the worker thread's COPIED context (propagate_context_to_thread) and dies with it; a probe confirmed the next attempt's context is clean. Resetting it would break digests running after the with-block. |
||
|
|
61cd299c6e |
fix(compression): attempt-generation ownership for overlapping stall-fallback attempts
Follow-up to #96634 (stall-fallback retry, #78981) addressing donovan-yohan's post-merge adversarial review. The stall path detaches a timed-out primary worker (fence cancel wins; future stays on the pool) and immediately runs the fallback against the SAME ContextCompressor, creating two verified races: 1. Late-primary snapshot restore: the detached primary's unwind called _restore_compressor_attempt_state with the PRIMARY's pre-attempt snapshot. Landing after the fallback's commit it rolled _previous_summary/cooldown/provenance/telemetry back to pre-primary values, silently discarding fallback-owned state. 2. Shared _compression_cancelled_check: the late primary's `finally` cleared the callback the fallback had just installed, so the fallback's F4 cancellation consult read None. Fix: a monotonic per-compressor attempt generation claimed under one module lock (_claim_compressor_attempt). Snapshot restores carry their claiming generation and no-op when stale; the cancelled-check set/clear moves into owner-stamped helpers (_install_compression_cancelled_check / _clear_compression_cancelled_check_if_owner) so only the installing attempt can clear it. The commit fence keeps owning COMMIT admission; the generation owns compressor-ATTRIBUTE writes — two boundaries. Legacy callers (attempt_generation=None) and slotted third-party compressors (generation 0) keep the historical unconditional behavior. Secondary review items: - Lean chunk digests during a stall-fallback retry now follow the summary onto the pinned healthy route: take_pinned_summary_route() echoes the consumed route into a context-local _SUMMARY_ROUTE_CONSUMED, and _build_chunk_digests passes attempt_summary_route_kwargs() (non-consuming) to call_llm. The pin's single-use contract for the SUMMARY call is unchanged — the main-model retry still never re-issues the pinned route. - Worker re-run repeating pre-compression callbacks: documented as an accepted limitation on _retry_compression_on_fallback_chain (built-ins idempotent; resuming mid-pipeline would couple the retry to host callback ordering). Tests (tests/agent/test_compression_attempt_ownership.py, 10 cases): deterministic interleavings for both races (late-primary restore no-ops + preserves fallback state; stale finally cannot clear the fallback's callback), legacy/slotted compatibility, digest route follow + context-locality of the consumed echo. Mutation-checked: reverting only the two prod files to origin/main fails the suite; restored stack green (21 passed incl. the original #78981 suite). The one red in the wider sweep (test_silence_cannot_approach_double_idle_timeout) is pre-existing on clean origin/main — verified independently. |