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

204 lines
7.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.
```text
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
```text
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.