feat(context,kernel): compression pipeline stage 3 — replay-safe tier summarizer

ContextSummarizedEvent (registered) keyed on stable session sequence, not the
ephemeral pack ordinal, so replay reuses the recorded summary artifact and never
re-calls the LLM (invariants #6/#8). TierContextSummarizer mirrors
JournalCompactionService for freeform context (tool outputs/docs/retrieved text)
the journal path doesn't cover. ContextState + DefaultContextReducer fold the
event; reducer replay-safety unit-tested.
This commit is contained in:
2026-07-01 14:03:47 +04:00
parent b50688df1d
commit e0c222392c
6 changed files with 151 additions and 1 deletions
@@ -0,0 +1,23 @@
package com.correx.core.events.events
import com.correx.core.events.types.ArtifactId
import com.correx.core.events.types.SessionId
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* Records that freeform context up through session sequence [coversThroughSequence] was
* summarized into [summaryArtifactId] at tier [tier]. Keyed on the stable event sequence (not
* the ephemeral per-assembly pack ordinal, which is re-stamped each build) so replay reuses
* the recorded summary deterministically and never re-calls the LLM (invariants #6/#8).
* [tier] 2 = light single-pass summary, 3 = summary-of-summaries.
*/
@Serializable
@SerialName("ContextSummarized")
data class ContextSummarizedEvent(
val sessionId: SessionId,
val coversThroughSequence: Long,
val summaryArtifactId: ArtifactId,
val tier: Int,
val entriesOmittedCount: Int,
) : EventPayload
@@ -61,6 +61,7 @@ import com.correx.core.events.events.StageCompletedEvent
import com.correx.core.events.events.PreemptRedirectBlockedEvent
import com.correx.core.events.events.PreemptRedirectEvent
import com.correx.core.events.events.StageFailedEvent
import com.correx.core.events.events.ContextSummarizedEvent
import com.correx.core.events.events.SteeringNoteAddedEvent
import com.correx.core.events.events.ToolCallAssessedEvent
import com.correx.core.events.events.ToolExecutionCompletedEvent
@@ -107,6 +108,7 @@ val eventModule = SerializersModule {
subclass(ToolCallAssessedEvent::class)
subclass(FileWrittenEvent::class)
subclass(SteeringNoteAddedEvent::class)
subclass(ContextSummarizedEvent::class)
subclass(PreemptRedirectEvent::class)
subclass(PreemptRedirectBlockedEvent::class)
subclass(InitialIntentEvent::class)