diff --git a/apps/tui/src/main/kotlin/com/correx/apps/tui/state/TuiState.kt b/apps/tui/src/main/kotlin/com/correx/apps/tui/state/TuiState.kt index 49070a04..8fb3ccbf 100644 --- a/apps/tui/src/main/kotlin/com/correx/apps/tui/state/TuiState.kt +++ b/apps/tui/src/main/kotlin/com/correx/apps/tui/state/TuiState.kt @@ -1,5 +1,7 @@ package com.correx.apps.tui.state +import com.correx.apps.server.protocol.ServerMessage + enum class InputMode { ROUTER, NAVIGATE, FILTER, STEER } enum class ToolDisplayStatus { REQUESTED, STARTED, COMPLETED, FAILED, REJECTED } @@ -33,6 +35,21 @@ data class TuiState( val providerType: ProviderType = ProviderType.LOCAL, val routerConnected: Boolean = false, val routerMessages: List = emptyList(), + /** + * True from connect until SnapshotComplete observed. Reset to true on Disconnected. + * When true, event-bearing messages are buffered in [pendingEvents]; snapshots are applied immediately. + */ + val snapshotPhase: Boolean = true, + /** + * FIFO buffer of event-bearing server messages received while snapshotPhase == true. + * Drained atomically when snapshot phase completes. + */ + val pendingEvents: List = emptyList(), + /** + * Per-session high-water mark keyed by SessionId.value. Updated only on applied live events. + * Used to deduplicate events during live streaming phase. + */ + val cursors: Map = emptyMap(), ) data class SessionSummary( diff --git a/apps/tui/src/test/kotlin/com/correx/apps/tui/reducer/RootReducerTest.kt b/apps/tui/src/test/kotlin/com/correx/apps/tui/reducer/RootReducerTest.kt index 8a35ef34..ad09b380 100644 --- a/apps/tui/src/test/kotlin/com/correx/apps/tui/reducer/RootReducerTest.kt +++ b/apps/tui/src/test/kotlin/com/correx/apps/tui/reducer/RootReducerTest.kt @@ -12,6 +12,14 @@ class RootReducerTest { private val fixedClock: () -> Long = { 1000L } + @Test + fun `TuiState defaults include snapshot phase, pending events, and cursors`() { + val state = TuiState() + assertEquals(true, state.snapshotPhase) + assertEquals(emptyList(), state.pendingEvents) + assertEquals(emptyMap(), state.cursors) + } + @Test fun `SubmitInput in ROUTER mode emits StartSession effect and resets buffer`() { val initial = TuiState(inputMode = InputMode.ROUTER, inputBuffer = "my-workflow")