Skip to content

Session compaction parity

Read this page when you need to know exactly what a session-compaction read surface can report — the posture states, reason codes, and quality-gate fields that every surface shares — and to rely on the durable contract that none of them ever carry raw transcript, prompt, or provider bodies.

Session compaction has one control-plane authority: the streaming compactor’s per-session posture snapshot. Read surfaces serialize that snapshot; they do not re-run compaction logic. All surfaces share one vocabulary so operator-visible state is identical across them. The read surfaces are GET /v1/sessions/{id}/compaction/status, get_session_compaction_status, bmo_get_session_compaction_status, the describe_context agent tool under compaction.session, bmo session status, the TUI Context hub, and the app read model.

The bounded posture state vocabulary (from internal/sessioncompaction/posture.go):

  • unavailable
  • disabled
  • idle
  • budget_warning
  • summary_linked
  • summary_missing
  • streaming_mechanical
  • streaming_semantic
  • streaming_ready
  • streaming_degraded

Posture resolution follows a fixed precedence so every surface reports the same state from the same snapshot:

  1. A broken summary link (summary_missing / summary_link_missing) is surfaced before any streaming phase.
  2. Then the streaming phase (streaming_mechanical, streaming_semantic, streaming_ready, streaming_degraded).
  3. Then linked-summary state (summary_linked).
  4. Then prompt-budget warn / exceeded / provider_context_error.

The fixed reason-code vocabulary (from internal/compaction/streaming/retention.go). Reason codes are bounded metadata: they never carry raw transcript text, prompt bodies, model responses, or provider error bodies.

Missing load-bearing facts:

  • missing_active_goal
  • missing_user_constraint
  • missing_permission_boundary
  • missing_active_path
  • missing_tool_outcome
  • missing_provider_pressure
  • missing_decision_state
  • missing_validation_result
  • summary_link_missing

Semantic structural:

  • semantic_truncated
  • semantic_token_count_invalid
  • semantic_error
  • semantic_timeout
  • semantic_canceled

Observation / boundary:

  • quality_unobserved

Operational (agent-side streaming path):

  • nil_mechanical_summary
  • save_session
  • summary_update_failed
  • swap_superseded
  • compaction_reason_unclassified

Posture exposes these quality-gate fields, scoped to the mechanical compaction version so a later run cannot reuse a prior verdict:

  • retention_ratio — bounded number
  • validation_passed — bool
  • validation_observed — bool
  • reasons — list of the bounded codes above

The retention shadow tracks nine load-bearing fact classes:

  • active_goal
  • user_constraint
  • permission_boundary
  • active_path
  • tool_outcome
  • provider_pressure
  • decision_state
  • validation_result
  • summary_link

Retention applies a two-tier policy: active_goal and active_path are majority / paraphrase-tolerant (retained at >= 50%); all other classes are fail-closed.

Beyond posture state, the snapshot carries bounded continuity metadata:

  • a continuity epoch
  • the latest trigger / status / reason
  • a small per-session event ring of recent compaction events

The same snapshot also carries the derived provider-turn round-pressure budget used by lifecycle admission:

  • closed_tool_round_warn_threshold
  • closed_tool_round_deny_threshold
  • diagnostic_repair_headroom_rounds

These are bounded integers derived from the session compactor budget, not a separate static control-plane policy.

All of this is bounded metadata; none of it carries raw bodies.

SurfaceHow it reads posture
GET /v1/sessions/{id}/compaction/statusSerializes the shared snapshot for HTTP clients
get_session_compaction_statusReturns the same JSON snapshot for native agent automation
bmo_get_session_compaction_statusReturns the same JSON snapshot for MCP clients
describe_contextSerializes the snapshot under compaction.session
bmo session statusRenders the snapshot for headless operator inspection
TUI Context hubShows the snapshot in the Compaction row
App read modelExposes the snapshot as SessionCompactionStatus

Snapshot.Admission on these surfaces is ephemeral / in-process. While the agent process is alive, describe_context.compaction.session and SessionCompactionStatus project the in-process LatestAdmission ring. After the agent process exits, bmo session status rebuilds from the in-process event ring and does not load persisted SQLite admissions. The snapshot always stamps admission_presence (observed or unobserved). unobserved is admission unobserved, not a finding that compaction did not run. An empty admission object is not a negative observation. Live payloads that cannot run SessionCompactionStatus stamp UnavailableSnapshot instead of omitting compaction. The TUI Context hub Compaction row is a live payload: on that error it shows StatusHint(UnavailableSnapshot) and does not keep a reaction-only hint as a silent substitute. Dedicated compaction-status HTTP/MCP/agent tools stay fail-closed on that error. Mechanical recovery credit is the envelope compare (material_change / material_change_observed), not work-convergence and not a dedicated Recovery type.