Multi-stage context-compaction runner.
The Claude Code paper describes Anthropic's compaction as a five-layer pipeline (Budget Reduction → Snip → Microcompact → Context Collapse → Auto-Compact / Summary), each layer cheaper than the next. The cheaper layers run first; the LLM-summary layer fires only when deterministic shrinkage couldn't get the conversation under target.
The pipeline implements the existing ExAthena.Compactor behaviour,
so loop.ex doesn't have to change — the kernel still calls
compactor.should_compact?/2 then compactor.compact/2. Internally
this module dispatches across a list of ExAthena.Compactor.Stage
modules.
Configuration
The stage list is read from state.meta[:compaction_pipeline],
falling back to ExAthena.Compactor.Stage.default_pipeline/0. Hosts
can swap individual stages or replace the list entirely.
Loop.run("hi",
provider: ...,
compactor: ExAthena.Compactor.Pipeline,
compaction_pipeline: [MyApp.MyStage, ExAthena.Compactors.Summary]
)Reactive recovery
When a mode signals :error_prompt_too_long, the kernel re-invokes
the pipeline with force: true, which runs every stage regardless
of cost. See run/3.
Summary
Functions
Run the pipeline. force: true makes every stage attempt
compaction unconditionally; this is the reactive-recovery path the
loop uses after a context-window error from the provider.
Functions
@spec run(ExAthena.Loop.State.t(), ExAthena.Compactor.estimate(), keyword()) :: ExAthena.Compactor.decision()
Run the pipeline. force: true makes every stage attempt
compaction unconditionally; this is the reactive-recovery path the
loop uses after a context-window error from the provider.
Returns {:compact, messages, metadata} if at least one stage
reduced the conversation, :skip if every stage declined, or
{:error, reason} on the first stage that surfaces an error.