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

5.3 KiB

Epic 2 — Session Lifecycle (FSM + Projection Layer)

completed deliverables

1. session state model (projection output)

implemented a deterministic session state representation derived entirely from event streams.

final structure:

  • SessionState (pure projection output)
  • SessionStatus
  • SessionEvent (FSM input domain)

key characteristics:

  • immutable
  • replay-safe
  • derived only from events
  • no identity leakage

session identity explicitly removed from projection state.


2. session identity boundary separation

introduced explicit separation between identity and state.

final model:

  • Session → identity wrapper
  • SessionState → projection result

structure:

Session(sessionId)
    ↓
SessionState

this removed previous anti-pattern:

  • embedding sessionId inside projection state
  • late-binding identity during replay fold

3. session FSM (deterministic lifecycle rules)

implemented deterministic finite state machine governing session lifecycle transitions.

states:

  • CREATED
  • ACTIVE
  • PAUSED
  • COMPLETED
  • FAILED
  • REPLAYED (diagnostic)

properties:

  • deterministic transitions
  • no side effects
  • replay-safe behavior
  • strictly event-driven evaluation

FSM is pure function:

(SessionStatus, SessionEvent) → SessionStatus

4. session event interpretation layer

introduced mapping layer between persisted events and domain FSM events.

components:

  • SessionEventMapper

responsibilities:

  • convert StoredEvent → SessionEvent
  • isolate domain semantics from persistence format

properties:

  • no state mutation
  • no replay logic
  • stateless transformation only

5. session projection engine

implemented SessionProjector as domain-specific projection over generic replay infrastructure.

responsibilities:

  • consumes ordered event stream
  • applies FSM transitions
  • produces deterministic session state
  • tracks lifecycle metadata

properties:

  • pure fold reducer
  • stateless across executions
  • deterministic replay behavior

state evolution:

StoredEvent → SessionEvent → FSM → SessionState

6. projection infrastructure alignment

aligned session model with generic replay engine (:core:events).

final integration:

  • Projection<S> reused as abstraction boundary
  • EventReplayer<S> drives deterministic reconstruction
  • SessionProjector plugs into generic replay system

no duplication of replay logic inside sessions.


7. session repository (identity boundary)

introduced repository as thin orchestration facade over replay engine.

final structure:

class DefaultSessionRepository(
    private val replayer: EventReplayer<SessionState>
) {

    fun getSession(sessionId: String): Session =
        Session(
            sessionId = sessionId,
            state = replayer.rebuild(sessionId)
        )
}

responsibilities:

  • binds session identity to replay result
  • no projection logic
  • no FSM logic
  • no event interpretation

8. replay integration

session lifecycle fully integrated into event-sourced replay pipeline.

final flow:

EventStore
    ↓
EventReplayer<SessionState>
    ↓
SessionProjector
    ↓
SessionState
    ↓
Session (identity wrapper)

system guarantees:

  • full replay determinism
  • identical event streams → identical session states
  • ordering enforced by store layer

9. test coverage completed

implemented deterministic coverage across session lifecycle:

  • session reconstruction from event stream
  • FSM transition correctness
  • invalid transition detection
  • replay determinism guarantees
  • empty stream handling
  • multi-event lifecycle correctness

introduced fixtures:

  • stored() event builder for deterministic event creation

aligned contract tests:

  • projection contract compliance
  • replay contract validation
  • event store contract enforcement

10. architectural cleanup (refactor milestone)

removed legacy session coupling patterns:

  • sessionId inside SessionState
  • implicit state hydration logic
  • repository-level replay duplication
  • ambiguous projection initialization patterns

removed or deprecated:

  • SessionCounterProjection as state-embedded counter logic (moved toward event-derived metrics approach)
  • FSM leakage into repository layer

final architecture after Epic 2

EventStore
    ↓
EventReplayer<SessionState>
    ↓
SessionProjector
    ↓
SessionState
    ↓
Session (identity wrapper)

major architectural outcomes

Epic 2 established:

  • strict separation between identity and state
  • deterministic FSM-driven session lifecycle
  • event-sourced state reconstruction model
  • reusable generic replay engine (:core:events)
  • domain-specific projection layer (:core:sessions)
  • repository as pure boundary adapter
  • fully replay-safe session lifecycle semantics

what Epic 2 intentionally does NOT include

not implemented:

  • workflow graph execution
  • transition DSL
  • orchestration runtime
  • stage execution engine
  • scheduling or async coordination
  • tool execution or kernel integration

those are explicitly deferred to Epic 3+


final state

Correx now has:

a deterministic, event-sourced session lifecycle system built on a generic replay engine, with strict separation between identity, state, and event interpretation, fully replay-safe and FSM-driven.