Skip to content

ADR-0081: Context-health surface (one view of context management)

Status pass (2026-10-18): the decision holds; the code now lives in agent/context_health.py, runtime/session_memory.py, cli/context_health.py.

Source: section ### ADR-0081: Context-health surface (one view of context management) of the project decisions log (project-iris-prd/13-decisions-and-rationale.md), extracted on 2026-10-18 for the Evarness repository. It predates the rename from IRIS and is kept as written.

Decision: Surface, in one place, how the harness bounds its working context. Three mechanisms previously each kept their own counsel: the conversation compactor (ADR-0079) bounds the multi-turn history to ~80% of the model window; the in-loop ContextBudgetController (ADR-0077 P3) splits a per-turn budget between the running transcript and the durable-memory block, evicting the oldest/lowest-value parts; and the surface-feedback spine (ADR-0078) suppresses proactive noise. Each logged; none was observable together. The new IrisRuntime.context_health(session_id) composes a single snapshot — window fill % + last compaction (tracked per session in _record_turn), the window-derived transcript/memory budget split + the latest in-loop prompt size and transcript eviction (fed by a lightweight budget_observer the AgenticCore calls each iteration, writing into a shared sink the runtime reads), and the suppression roll-up (SurfaceFeedbackStore.summary() → active-suppression counts by subsystem). The pure composition lives in src/iris_harness/core/context_health.py; surfaces are GET /context-health, iris context-health (renders the live API), and a Context-budget panel on the web Health screen (thin renderer).

Rationale: "Keep only what's needed, evict the rest" was implemented across three subsystems but invisible — you couldn't answer "how full is the window right now, what did the last compaction drop, how much is the loop evicting, how much am I suppressing?" without reading logs across three packages. Making the brain's memory management measurable in one read is the natural capstone to the compaction/suppression/learning-activation work: it turns a set of internal guardrails into something the user (and the agent) can watch and reason about. The budget observer is deliberately decoupled (a callback into a shared dict, fired before the kernel check so it works on the legacy no-kernel path too) so the hot loop takes only a dict write per iteration. Wired to the primary system react loop; the niche email loop is intentionally excluded to keep the budget split unambiguous. Full design: docs/architecture/memory-subsystem.md (context-health note); narrative docs/blog/2026-06-28-one-look-at-the-brain.md.