The summary produced by auto-compaction lived only in the engine's in-memory
`compaction_state`; the transcript's `compacted` notice carried a generic
sentence, so a saved session, an exported trajectory or a run record
showed that compaction happened but not what the model's memory was replaced
with (the app's session record keeps only the latest state).
- `_compaction_record()` returns `compaction_state.as_dict()` (summary text,
working state, boundary index, user-message list, summarizer model,
created_at, trimmed flag).
- Both compaction sites (the between-turn checkpoint and the context-overflow
retry) attach it to the persisted `compacted` notice as `compaction` and to
the COMPACTED event payload. Notices never reach a provider.
Tests: tests/test_compaction_persisted_summary.py — record equals the state,
summary text present, JSON-serialisable, event carries it; the trim fallback
records trimmed=True with the placeholder; nothing reaches the provider.