Skip to content

feat(agent-loop): compaction circuit breaker (IMPROVEMENTS_PLAN #1) - #220

Merged
yogthos merged 1 commit into
mainfrom
feat/improve-1-compaction-circuit-breaker
May 29, 2026
Merged

feat(agent-loop): compaction circuit breaker (IMPROVEMENTS_PLAN #1)#220
yogthos merged 1 commit into
mainfrom
feat/improve-1-compaction-circuit-breaker

Conversation

@yogthos

@yogthos yogthos commented May 29, 2026

Copy link
Copy Markdown
Collaborator

First of the 5 IMPROVEMENTS_PLAN phases — one PR per feature for review.

Problem

A failing summarizer (network errors / invalid summaries / model garbage) was retried on every fold trigger, silently falling back to pruned-only context each time — burning API calls for the whole run.

Fix

Per-run consecutive-failure counter:

  • run_compaction_pass[_with_focus] now takes the current failure count and returns a SummaryOutcome (Succeeded/Failed/Skipped).
  • run_loop folds that into compaction_failures via record_compaction_outcome at all three call sites (turn-start fold, post-usage fold, exit-with-summary).
  • At MAX_CONSECUTIVE_COMPACTION_FAILURES = 3, the pass skips the LLM summarizer (logs circuit breaker open); the cheap prune_tool_outputs still runs, so context stays bounded.
  • Per-run (resets on success and on a fresh run_loop), matching the plan's design decision.

Tests

  • Pure counter logic (record_compaction_outcome: reset/increment/skip).
  • End-to-end: summarizer invoked once per sub-threshold attempt, then not called once the breaker opens, with the prune-only fallback still shrinking context.

2135 pass under the full feature matrix at -D warnings.

Next phases (each its own PR): #3 aggressive prune tier → #4 snip feedback loop → #2 post-compaction file restore → #5 report enrichment.

When the summarizer keeps failing (network errors, invalid summaries,
model garbage), every fold trigger re-called the LLM and silently fell
back to pruned-only context — wasting API calls every turn.

Add a per-run consecutive-failure counter. `run_compaction_pass[_with_focus]`
now takes the current count and returns a `SummaryOutcome`
(Succeeded / Failed / Skipped); `run_loop` folds that into
`compaction_failures` via `record_compaction_outcome`. Once the count
reaches MAX_CONSECUTIVE_COMPACTION_FAILURES (3), the pass skips the LLM
summarizer entirely (logs "circuit breaker open") — the cheap
`prune_tool_outputs` pass still runs, so context can't grow unbounded.
Counter resets on the next successful summary; it's per-run, so a fresh
run_loop starts clean.

Tests: pure `record_compaction_outcome` counter logic, and an
end-to-end test asserting the summarizer is invoked once per
sub-threshold attempt then NOT called once the breaker opens, with the
prune-only fallback still firing. 2135 pass at -D warnings.
@yogthos
yogthos merged commit 59ea0db into main May 29, 2026
9 checks passed
@yogthos
yogthos deleted the feat/improve-1-compaction-circuit-breaker branch May 29, 2026 21:05
allen-munsch pushed a commit to allen-munsch/dirge that referenced this pull request May 29, 2026
…PLAN #3)

The per-result cap (cap_oversized_tool_results) was a flat 3000 tokens
regardless of context pressure. Near the limit, a single uncapped tool
result could push the NEXT request over before the reactive 75%
post-response fold fires.

Add a tiered cap: above AGGRESSIVE_CAP_THRESHOLD (60% estimated context)
the per-result cap tightens to AGGRESSIVE_RESULT_CAP_TOKENS (1000) via a
pure `tiered_result_cap(estimate, ctx_max)` helper; below it stays at
3000. The 60% threshold sits below the 75% fold trigger so the tighter
cap has room to work first. Wired at the pre-send cap site in run_loop.

Unit test for the tiering (normal below 60%, strict boundary at 60%,
aggressive above). 2136 pass at -D warnings.

Stacked on the circuit-breaker branch (PR dirge-code#220).
allen-munsch pushed a commit to allen-munsch/dirge that referenced this pull request Jun 3, 2026
…action-circuit-breaker

feat(agent-loop): compaction circuit breaker (IMPROVEMENTS_PLAN #1)
allen-munsch pushed a commit to allen-munsch/dirge that referenced this pull request Jun 3, 2026
…PLAN #3)

The per-result cap (cap_oversized_tool_results) was a flat 3000 tokens
regardless of context pressure. Near the limit, a single uncapped tool
result could push the NEXT request over before the reactive 75%
post-response fold fires.

Add a tiered cap: above AGGRESSIVE_CAP_THRESHOLD (60% estimated context)
the per-result cap tightens to AGGRESSIVE_RESULT_CAP_TOKENS (1000) via a
pure `tiered_result_cap(estimate, ctx_max)` helper; below it stays at
3000. The 60% threshold sits below the 75% fold trigger so the tighter
cap has room to work first. Wired at the pre-send cap site in run_loop.

Unit test for the tiering (normal below 60%, strict boundary at 60%,
aggressive above). 2136 pass at -D warnings.

Stacked on the circuit-breaker branch (PR dirge-code#220).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant