Files
correx/docs/epics/epic-7-resolution.md

7.7 KiB
Raw Permalink Blame History

Epic 7 — Context Engine (Deterministic Context Synthesis Layer)

completed deliverables

1. context identity

introduced ContextPackId and ContextEntryId as type aliases to TypeId in core:events.

  • lives alongside other shared vocabulary types (SessionId, ArtifactId, etc.)
  • available to all modules depending on :core:events

2. context lifecycle events

introduced five context lifecycle events in core:events, covering the full pack building pipeline.

events:

  • ContextBuildingStartedEvent(sessionId, stageId)
  • ContextPackBuiltEvent(contextPackId, sessionId, stageId, budgetUsed, budgetLimit)
  • CompressionAppliedEvent(contextPackId, layer, entriesRemoved, strategyApplied)
  • LayerTruncatedEvent(contextPackId, layer, entriesDropped, reason)
  • ContextBuildingFailedEvent(sessionId, stageId, reason)

properties:

  • all registered in eventModule polymorphic block
  • emitted during pack assembly — enables deterministic replay of compression decisions
  • layer and strategyApplied carried as String — avoids circular dependency with core:context

3. context layer model

introduced ContextLayer as a serializable enum with five distinct layers.

L0  live execution      [active request, current tool output, pending approval]
L1  stage-local context [artifacts and receipts from the current stage]
L2  compressed session  [summaries of completed stages; kept under a token cap]
L3  project memory      [persistent facts, architecture decisions, key outputs]
L4  archival history    [full event log; not used for inference]

models receive a ContextPack built from L0L2; L3 optionally injected if relevant. L4 is archival only.


4. context pack contract types

introduced the core domain types for context synthesis.

final structures:

  • ContextEntry(id, layer, content, sourceType, sourceId, tokenEstimate) — typed reference to an event, artifact excerpt, summary, or policy snippet
  • CompressionMetadata(appliedStrategies, truncatedLayers, entriesDropped) — audit trail of compression decisions
  • ContextPack(id, sessionId, stageId, layers, budgetUsed, budgetLimit, compressionMetadata) — the final assembled context artifact
  • TokenBudget(limit, used) — transient computation value with remaining, consume(), and canFit() helpers; intentionally not serializable

5. compression pipeline

introduced a content-type-specific, rule-based, deterministic compression pipeline. zero model calls.

final structure:

  • CompressionStrategy (sealed interface, five content-type-specific implementations):
    • ToolLog — deduplicate identical content, drop oldest when over budget
    • Conversation — keep last N verbatim, drop oldest first under budget pressure
    • Artifact — keep most recent entry per sourceId
    • SteeringNote — always retained verbatim, never dropped
    • EventHistory — always retained; already-compressed DecisionPoints from prior stages
  • ContextCompressor (interface)
  • DefaultContextCompressor — applies strategies deterministically; drop order: L2 first, then L1; L0 is never dropped

key invariant:

same input always produces the same output — compression is replay-safe


6. context state and projection

introduced the standard event-sourced pattern for context state.

final structures:

  • ContextState(builtPackIds, buildingInProgress) — fully rebuildable from events; no external data
  • ContextReducer (interface)
  • DefaultContextReducer — handles ContextBuildingStartedEvent, ContextPackBuiltEvent, ContextBuildingFailedEvent; passes all others through unchanged
  • ContextProjector — implements Projection<ContextState>; delegates to reducer

7. context pack builder

introduced a pure, side-effect-free context pack assembly pipeline.

final structures:

  • ContextPackBuilder (interface)
  • DefaultContextPackBuilder — compresses entries, groups by layer, tracks budget usage and truncation metadata

key invariant enforced:

entries with sourceType of "steeringNote" or "eventHistory" are partitioned before compression and always retained, regardless of budget pressure

  • DecisionPointBuilder (interface)
  • DefaultDecisionPointBuilder — extracts only L0 and L1 entries from a pack for model inference calls

8. context repository

introduced DefaultContextRepository over EventReplayer<ContextState>, following the established repository pattern.

  • single method: getContextState(sessionId): ContextState
  • delegates to replayer.rebuild(sessionId)
  • no business logic — thin wiring layer

9. context serialization module

introduced contextModule: SerializersModule in core:context.

  • polymorphic block scaffolded for future extension
  • follows the same pattern as eventModule and artifactModule

10. test coverage

implemented deterministic and projection tests covering all core behaviors.

deterministic tests (27):

  • compression strategies: determinism, layer drop order, never-drop invariants (SteeringNote, EventHistory), artifact deduplication, tool log deduplication
  • token budget: arithmetic correctness, immutability, exhaustion, canFit semantics
  • pack builder: layer grouping, budget tracking, budget enforcement, decision point filtering, steering note retention under budget pressure, empty entries

projection tests (22):

  • reducer: all three context event transitions, pass-through for unrelated events
  • projector: initial state, deterministic replay

final architecture after Epic 7

ContextBuildingStartedEvent → ContextPackBuiltEvent (via core:events)
    ↓
ContextState (rebuilt from events via DefaultContextReducer + ContextProjector)
    ↓
DefaultContextPackBuilder (pure function)
 ├── pins: SteeringNote + EventHistory entries (never dropped)
 ├── compresses: remaining entries via DefaultContextCompressor
 │    └── strategy dispatch: ToolLog / Conversation / Artifact / SteeringNote / EventHistory
 │         └── drop order: L2 → L1 (L0 never dropped)
 └── assembles: ContextPack with layer map + budget metadata
    ↓
DefaultDecisionPointBuilder → L0 + L1 entries (sent to model for inference)

major architectural outcomes

Epic 7 established:

  • deterministic, rule-based context synthesis — zero model calls for compression
  • five-layer context model separating live execution from compressed history
  • content-type-specific compression strategies with never-drop invariants for critical entries
  • token budget enforcement with correct layer eviction priority
  • event-sourced context state fully rebuildable from the event log
  • pack builder as a pure function — no IO, no side effects, replay-safe

what Epic 7 intentionally does NOT include

not implemented:

  • policy injection into context packs (step 5 of the pipeline — deferred)
  • event retrieval and projection wiring for pack building (caller provides entries)
  • L3/L4 storage and retrieval (infrastructure concern)
  • router context isolation (separate L2 memory for the router — deferred)
  • semantic summarization — no model-assisted compression of any kind
  • cross-session context leaking prevention (enforced structurally by session scoping)
  • observability hooks beyond event emission

those are explicitly deferred to later epics.


final state

Correx now has:

a deterministic, rule-based context synthesis engine that assembles token-budgeted, layered context packs from events and artifacts — with content-type-specific compression strategies, strict never-drop invariants for steering notes and decision history, and full event-sourced state tracking — ensuring models always receive minimal, relevant, reproducible context without any model calls in the compression path.