Skip to the content.

fak guard ↔ Codex integrated compaction: runtime alignment

Operational companion to BUILT-IN-COMPACTION-AUDIT-2026-07-06 (which covers why built-in compaction is conceptually weak). This note covers how fak guard actually aligns with Codex’s integrated compaction at runtime, backed by a fleet audit of the local Codex rollout store, and the monitoring + best-practice defaults that follow.

Bottom line

fak guard enforces one resident-token budget (~96K) for a guarded session, but it has to implement that budget two different ways because the model is reached over two different wires:

Wire Who compacts Mechanism Budget knob
Anthropic Messages (/v1/messages) fak itself cache-prefix-preserving suffix shed — drops the uncached middle, keeps the byte-identical cached prefix; no summary, lossless prefix DefaultCompactHistoryBudget=48000 (interactive) / HeadlessCompactHistoryBudget=96000 (headless) — internal/gateway/gateway.go
OpenAI Responses (Codex) Codex, natively Codex’s built-in summarize-and-discard auto-compaction (lossy) fak sets model_auto_compact_token_limit=96000 at launch — cmd/fak/codex_launcher.go, cmd/dispatchworker/guard.go

On the wire fak controls (Anthropic) it uses the stronger lossless cut. On Codex’s wire it cannot run that cut (wrong protocol), so it delegates to Codex’s native compaction and configures its trigger to the same 96K budget. That single launch override (codex_launcher.go:244) is the whole alignment seam.

Why fak pins Codex to 96K (and why compaction “looks light”)

Codex’s out-of-the-box model_auto_compact_token_limit sits near the model window (~245K of a 258K effective window). Left alone, two things break for a guarded fleet:

  1. Guarded sessions appear never to compact — they ride at ~245K until the window is nearly full, which is exactly the “fires too late / context rot” failure the conceptual note warns about (§”It often fires too late”).
  2. Headless dispatch workers sit far above the 96K cache-economics budget the rest of fak is tuned to (#4253), destroying cross-worker prefix reuse.

So fak codex / the dispatch worker inject -c model_auto_compact_token_limit=96000. A later operator -c remains authoritative.

This directly explains the operator-visible “compaction even when the context looks light.” The Codex TUI shows occupancy as a fraction of the 258K model window; compaction fires at the 96K budget = ~37% of that window. It is not premature — it is the intended budget. The gap is a display mismatch (window shown, budget enforced), not a bug. See the fleet evidence below.

Fleet evidence (2026-07-15 audit)

Audited the full local Codex rollout store (~/.codex/sessions/**/*.jsonl, ~2,967 files) with the new monitor tools/codex_turn_health.py:

OpenAI’s own Codex prompting guide corroborates the turn-inflation half: preambles/plan/status narration “can cause the model to stop abruptly before the rollout is complete” — precisely the talk-not-act and preamble-noop turns.

Best-practice defaults

Posture: additive and reversible on the shared trunk; keep coding-quality knobs high.

Keep as-is (already correct):

Safe, additive monitoring default (this change):

Recommended, but gated behind review (do not flip unilaterally):

Monitoring — how to watch this going forward

Run the monitor (defaults to ~/.codex/sessions, honours CODEX_HOME):

python3 tools/codex_turn_health.py            # full report + exit 1 on any flag
python3 tools/codex_turn_health.py --limit 200   # last 200 rollout files

Signals it emits (all fail-closed to exit 1):

Plus a compaction histogram (near_budget_96k, near_window_200k_plus, premature_lt40k) that makes the two-wire budget posture visible at a glance — a healthy guarded fleet should sit in near_budget_96k, not 200k_plus.

Forward opportunities

  1. Close the gap on Codex’s wire with its own hooks. The conceptual note catalogs Codex PreCompact/PostCompact hooks. fak already witnesses/pins state elsewhere; wiring a PreCompact hook to record must-keep pointers and a PostCompact probe to verify they survived would give Codex’s lossy native compaction some of the lossless discipline fak applies on the Anthropic wire — directly answering the conceptual note’s “verify compaction” and “keep raw evidence addressable” targets.
  2. Fix the display mismatch so a 96K compaction on a 258K window reads as “at budget,” not “compacting when nearly empty.”
  3. Stuck-loop kill switch: the monitor already identifies ≥N consecutive zero-tool turns; a live detector could halt a session at turn 3 instead of letting 019f2ae9 burn 44.