# `Planck.Agent.Hooks.Compactor.Default`
[🔗](https://github.com/alexdesousa/planck/blob/v0.2.2/lib/planck/agent/hooks/compactor/default.ex#L1)

Built-in `Planck.Agent.Hooks.Compactor` implementation.

Used whenever `state.compactor` is `nil` — see `Planck.Agent.Hooks.Compactor`'s
own moduledoc for the dispatch rules. Not special-cased by the dispatcher in
any other way: this module satisfies the same behaviour a sidecar-hosted
custom compactor would, and could be named explicitly via `AgentSpec.compactor`
too.

## Strategy

The messages since the last summary checkpoint are split into a recency
floor (always kept verbatim — mirrors the "at least the last message is
always kept" invariant) and an older bucket. The older bucket is summarized
as one plain-text block by a real, ephemeral `Planck.Agent` — not asked for
structured per-message output. An earlier version of this asked the
delegate for per-message keep/drop verdicts as JSON; that turned out to be
the wrong shape for a compactor that has to work with whatever model is
configured, not a specific one: producing well-formed JSON with correct
message-id references is a much less reliable task for a weak/small model
than writing a plain summary is, and a compactor that only works with
capable models defeats its own "works everywhere" purpose. Per-message
relevance judgment still has a natural home — a fast classifier-style
model whose native output already is one answer per item — just not here.

The delegate agent has no `team_id` (invisible to `list_team`, which only
enumerates registered team members), no `session_id` (nothing is persisted
for it), and no tools — a pure text-in/text-out summarization call. It is
`Process.monitor/1`-ed, not `Process.link/1`-ed: a crashing delegate must
degrade to `:skip`, not crash the compacting agent (worker or orchestrator).
It is always stopped before this module returns, on every exit path.

`compact/3` still blocks the compacting agent's own `GenServer` for the
duration — that's deliberate, unchanged from before (see
`Planck.Agent.Hooks.Compactor`'s moduledoc on `on_compacting`/`on_compacted`).
What must *not* happen inside that `GenServer` callback is a raw `receive`
waiting on the delegate's PubSub events: the delegate is a real
`Planck.Agent` broadcasting `:turn_start`/`:text_delta`/`:usage_delta`/etc,
not just `:turn_end`, and any of those left unmatched by a receive done
directly in the compacting agent's own process would sit in *its* mailbox,
corrupting its own `handle_info/2` dispatch once this call returns. So the
actual subscribe/prompt/await sequence runs inside a dedicated,
`async_nolink` `Task` instead — its mailbox and PubSub subscription are
simply discarded when it exits, regardless of what's left in it, the same
isolation `Tools.call_agent`'s own await loop already relies on for this
exact reason. `compact/3` blocks on awaiting that task, not on a receive
in its own process.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
