281 lines
5.3 KiB
Markdown
281 lines
5.3 KiB
Markdown
# 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:
|
|
|
|
```text id="s1"
|
|
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:
|
|
|
|
```text id="s2"
|
|
(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:
|
|
|
|
```text id="s3"
|
|
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:
|
|
|
|
```kotlin id="s4"
|
|
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:
|
|
|
|
```text id="s5"
|
|
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
|
|
|
|
```text id="s6"
|
|
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.
|