Sprint 1b — replace the flat max_context_chars=60000 default with
per-mode budgets matching the peak bucket each mode achieved on
the 2026-05-02 bench:
quote → 24000 (peak 16-32KB)
claim_lattice_pointer → 24000 (peak 16-32KB)
claim_lattice (JSON) → 48000 (peak 32-64KB)
The flat 60K was past peak for quote/pointer (which degrade after
32 KB) and only marginally above peak for JSON. The bench's
recommended-context-budget table now flows back into the policy
defaults — operator-driven landing per the five-step algorithm
step 5: surface, don't auto-apply. The mapping lives in
DEFAULT_QUERY_POLICY so any tuning bumps governance_policy_hash
and partitions the cache namespace cleanly.
API boundary stays backward-compatible: an explicit
max_context_chars= caller value still wins. The per-mode default
fires only when the caller passes None (or omits the arg).
CLI: --max-context-chars default flips to None; help text spells
out the per-mode fallback.
Smoke (5-question fixture) confirmed no regressions vs the
pre-change baseline:
quote 2/5 → 5/5 (+3)
pointer 0/5 → 1/5 (+1)
JSON 5/5 → 5/5 (flat — already at ceiling on this fixture)
Quote's +3 is the unexpected win: the smaller 24K budget surfaces
tighter-relevance top-K instead of drowning the model in filler.
The full bench (~50 min) is the real scoreboard but smoke shape
matches the bench's predicted lift direction.