Commit Graph

283 Commits

Author SHA1 Message Date
kami d0e3550025 feat(tui-02): complete Channel(UNLIMITED) migration for _connection field in TuiWsClient
Migrate _connection from MutableSharedFlow + tryEmit to Channel(UNLIMITED) + send to ensure no connection events are dropped under high load. Removes unused MutableSharedFlow and asSharedFlow imports. Changes public connection property type from SharedFlow to Flow for consistency with messages field.

- Replace MutableSharedFlow with Channel(UNLIMITED) for _connection
- Convert all _connection.tryEmit() calls to _connection.send()
- Update public connection property to use receiveAsFlow()
- Add TuiWsClientConnectionChannelTest with 10k event no-drop verification
2026-05-25 01:08:35 +04:00
kami 2e11b7c0d0 feat(tui-02): replace SharedFlow + tryEmit with Channel(UNLIMITED) in TuiWsClient to eliminate silent message drops
Replace MutableSharedFlow + tryEmit pattern in _messages field with Channel(UNLIMITED) + receiveAsFlow() to guarantee no message loss under high throughput. The extraBufferCapacity-based SharedFlow silently dropped messages when subscribers were slow; Channel(UNLIMITED) provides deterministic FIFO behavior with no drops.

Updated public messages property type from SharedFlow to Flow for compatibility.
Changed both message emission sites (connect() and connectSession()) from tryEmit() to send().
Added TuiWsClientChannelTest with 10k message no-drop verification.

Acceptance criteria:
- Channel(UNLIMITED) used for _messages instead of SharedFlow
- receiveAsFlow() converts channel to Flow
- send() replaces tryEmit() for message emission
- connectSession/disconnectSession/sessionStreamJob/sessionWsSession intact
- 10k message test verifies no-drop guarantee
2026-05-25 01:02:18 +04:00
kami 78379d244f feat(tui-01): add snapshot phase, pending events, and cursor tracking to TuiState
Add three new fields to support the snapshot/live streaming protocol phase:
- snapshotPhase: Boolean (true during initial snapshot)
- pendingEvents: List<ServerMessage> (FIFO buffer during snapshot)
- cursors: Map<String, Long> (per-session high-water marks for deduplication)

All fields include KDoc documenting their invariants and purpose. Additive
change only; all existing tests continue to pass.
2026-05-25 00:31:49 +04:00
kami 1f742c0dfd feat(server-05): replace snapshot-then-subscribe with buffer-then-drain in GlobalStreamHandler
Establishes subscribeAll() before replaySnapshot() so no event can slip between the
projection read and live forwarding. Removes liveStreamJobs map and per-session forwarder
spawn from handleStartSession; all live forwarding flows through the single global
subscription. Closes findings #1 (race) and #5 (truth sources).

Tests cover happy path, race (x100), empty sessions, and shutdown/leak cases.
2026-05-25 00:19:22 +04:00
kami 850c6df743 fix(build): resolve three failing tests across integration and tui modules
SessionOrchestratorIntegrationTest: wire approvalRepository into
OrchestratorRepositories constructor which gained the field in the kernel
refactor. TambouiKeyMapperTest: correct ctrl-h to alt-h — the mapper has
always placed ToggleApprovalOverlay under the Alt branch, not Ctrl.
SessionOrchestrator.emit: replace substring(0,7) with take(7) to avoid
StringIndexOutOfBoundsException when session IDs are shorter than 7 chars.
2026-05-24 23:11:17 +04:00
kami 14141f2f72 feat(server-04): fix snapshot cursor order, deterministic approvals, unconditional SnapshotComplete
Capture lastGlobalSequence() before any projection read to anchor the
buffer-drain window; capture lastSequence(sessionId) before each session's
projection read. SessionSnapshot.lastSequence now carries the global cursor
shared across all sessions in the batch. pendingApprovals populated from
filtered approval state and sorted by (timestamp, requestId) for deterministic
ordering. SnapshotComplete emitted unconditionally including the zero-sessions
case. Four new tests: zero-sessions, SnapshotComplete-last ordering, global
cursor isolation, and per-session cursor value.
2026-05-24 23:01:21 +04:00
kami ac05ad8733 chore(clean up): remove unused imports, unnecessary object impls, concurrency/coroutine issues, trailing commas, etc. 2026-05-24 22:56:19 +04:00
kami 71aac8afc9 feat(server-03): log unmapped events at DEBUG in DomainEventMapper
Adds a file-private SLF4J logger and replaces the silent else->null branch
with a debug log line that names the payload type, sessionId, and sequence.
Test extended with a log-capture case that verifies exactly one DEBUG event
is emitted containing the payload class name for unrecognised event types.
2026-05-24 22:36:59 +04:00
kami 70420083ac feat(server-02): promote EventStore to global-sequence store with subscribeAll
StoredEvent gains sessionSequence: Long (per-session monotonic); existing
sequence field becomes the global monotonic cursor across the entire store.
SqliteEventStore allocates both counters inside the same BEGIN IMMEDIATE
transaction and emits to a global MutableSharedFlow after commit.
InMemoryEventStore mirrors this with an AtomicLong global counter and a
suspend-on-overflow SharedFlow. EventStore interface gains subscribeAll()
and lastGlobalSequence(). Contract tests updated and extended to cover
global-sequence and cross-session subscribeAll invariants.
2026-05-24 22:23:43 +04:00
kami 0cfb784187 feat(server-01): extend wire protocol with sequence cursors and SnapshotComplete
Every event-derived ServerMessage gains sequence (global) and sessionSequence
(per-session) cursor fields. SessionSnapshot adds lastSequence and
lastSessionSequence at projection-read time. SnapshotComplete data object
terminates the snapshot phase and is registered in the polymorphic module.
replaySnapshot() now emits SnapshotComplete after all SessionSnapshot messages.
SessionStarted audit deferred with TODO comment. DomainEventMapper propagates
both cursors to all mapped messages including InferenceCompleted.
2026-05-24 22:23:35 +04:00
kami fc7b879891 feature(event-sourcing): baseline for the architecture review fixes.
- fixed the tool overlay in tui.
- fixed tool calling - added schemas.
- getting all sessionIds via event store.
- instead of sending all events on the replay - there's a new way for replaying.
- session snapshot is now a thing getting sent for previously created sessions.
- added logging to important parts.
- revert workflowId from WorkflowCompletedEvent.
2026-05-24 18:57:56 +04:00
kami f827685ed0 chore(damn): detekt, build, tests, formatting
fixed detekt issues where possible.
fixed disttar failing build because tools is added twice in the server module.
added workflowId where required.
fixed some tests not being recognized because of runBlocking without explicit return type.
formatting + imports.
2026-05-22 00:10:05 +04:00
kami 2c459da009 feat(router): implement Epic 14 — core:router module
Implements the full conversational router facade: RouterState, RouterReducer,
RouterProjector, RouterRepository, RouterContextBuilder, RouterFacade, protocol
types, WebSocket wiring, infrastructure factory, and deterministic test suite.

Also fixes spec divergences found in post-implementation review:
- Add SteeringNote domain object to core:context (epic prerequisite)
- Rename RouterFacade.handleChat → onUserInput per spec interface contract
- Add in-memory ConcurrentHashMap conversation history to DefaultRouterFacade
- Make RouterRepository.getRouterState suspend
- Rename RouterConfig.keepLast → conversationKeepLast, fix defaults (6, 4096)
- Refactor InfrastructureModule.createRouterFacade to self-assemble internally
- Fix FileReadTool: allowedPaths was dead constructor param (@SuppressUnusedParameter);
  now stored as private val and enforced in validateRequest
- Disable koverVerify on modules tested via testing/ submodules or with
  hardware/integration dependencies (24 modules); build gate now passes clean
2026-05-21 15:06:20 +04:00
kami ac5ee9c3e0 feat(tui): redesign layout per spec v2 — 3-panel top row, 4-mode input bar, tamboui 0.3.0
- Layout: status bar (borderless), horizontal top row (sessions 30% / active 30% / tools 40%), router fill, input bar fixed
- Components: rewrote all 5 + added ToolsPanel; all accept TuiState directly
- InputBar: 4 modes (ROUTER/NAVIGATE/FILTER/STEER) with context-sensitive keybind hints
- RouterPanel: inline approval/event overlays as last-child text panels
- StatusBar: borderless row with model, providerType, session count, approval badge
- SessionList: manual column/row rendering, no list widget, overflow truncation
- tamboui bumped to 0.3.0
- TambouiKeyMapper: ctrl+key required for all keybinds, bare chars always
  go to input buffer.
- KeyResolver: Quit is ROUTER-only (not global); NavUp/NavDown handled in
  ROUTER as well as NAVIGATE; Filter in ROUTER maps to OpenFilter; CharInput
  in ROUTER returns null (semantic chars handled upstream by mapper).
2026-05-20 01:24:26 +04:00
kami a855eaee45 fix(tui): update tests to match refactored InputMode and flat TuiState
Sync all TUI reducer and input tests with the state model refactor:
InputMode.None/WorkflowId/SteeringNote/Filter → ROUTER/NAVIGATE/STEER/FILTER;
InputState(mode, text) → TuiState(inputMode, inputBuffer); fix SessionStarted
effect assertion to expect ConnectSession.
2026-05-20 00:48:14 +04:00
kami 7ac3a1ff79 feat(tui): enrich state model and refactor input mode into TuiState
Lifts inputMode/inputBuffer out of InputState into top-level TuiState,
renames InputMode variants to ROUTER/NAVIGATE/FILTER/STEER, adds
TuiToolRecord and TuiEventEntry for per-session tool/event history,
expands SessionsReducer to track tool lifecycle and recent events, and
adds ToggleApprovalOverlay/ToggleEventOverlay/EnterSteer actions.
2026-05-20 00:36:46 +04:00
kami 3365208d3a chore(cleanup): remove dead Module stubs and unused imports; restore deferred files
Deletes 21 Module.kt scaffolding objects that were never wired into any DI
registry. Removes unused imports across 8 production and 3 test files.

Restores StageExecutor, CyclePolicyResolver, PolicyValidation, and
ReplayContractTest — these are deferred features, not dead code.
2026-05-19 13:43:21 +04:00
kami 1c70511436 chore(cleanup): delete confirmed-dead files with no live references
Removes 6 files audited as fully unused: StageExecutor interface (shadowed
by kernel), CyclePolicyResolver and PolicyValidation (deferred cycle policy),
ApprovalRoutes (never registered), TuiNavigation (superseded by reducer),
and ReplayContractTest abstract class (no concrete subclasses).

ArtifactRelationshipType and CyclePolicy were audited but retained —
both are actively referenced by production code.
2026-05-19 12:55:27 +04:00
kami 71a73a4fa2 chore(audit): tool path resolution, config file, dead code removal, static analysis cleanup
Tool fixes:
- FileWriteTool, FileEditTool: resolve relative paths against workingDir instead of JVM cwd
- FileReadTool: remove allowedPaths restriction — reads are unrestricted
- ShellTool: add workingDir for ProcessBuilder, remove environment().clear(), fail-open when allowedExecutables empty

Config:
- Add [tools] section to config.toml: sandbox_root, working_dir, shell_allowed_executables, default_system_prompt_path
- Three-level resolution: env var > config file > hardcoded default
- OrchestrationConfig sandboxRoot and defaultSystemPromptPath now sourced from CorrexConfig
- Single defaultOrchestrationConfig in ServerModule, shared by SessionRoutes and GlobalStreamHandler

Dead code:
- Delete EventTypes.kt — orphaned string constants duplicating serialization annotations

Static analysis:
- Remove 10 unused imports across 9 files
- Remove redundant return in ReplayOrchestrator
- Remove redundant suspend from ApprovalCoordinator.handleResponse
- Fix unreachable InputMode.None branch in InputBar
- Enable full detekt rule sets in detekt.yml
2026-05-19 12:48:47 +04:00
kami f32d400138 feat(server+tui): event bridge — live streaming and historical replay
- SessionEventBridge: replaySnapshot() sends all historical events on connect;
  streamLive(sessionId) subscribes to live event flow per session
- DomainEventMapper: maps 14 domain event types to ServerMessage; reads
  InferenceCompleted response text from ArtifactStore with empty-string fallback
- GlobalStreamHandler: wires bridge on connect for replay, launches per-session
  live-stream job on StartSession, cancels all jobs on disconnect; removes
  ProtocolError("ping") heartbeat hack
- SessionStreamHandler: fixes replay to use DomainEventMapper instead of
  emitting SessionStarted for every event; injects real artifactStore;
  removes ProtocolError("ping") heartbeat; adds structured logging throughout
- Main: startup log block showing port, model config, sandbox, stores, tools,
  providers
- SessionsReducer: StageCompleted/StageFailed now clears currentStage; adds
  5 missing tests (InferenceCompleted, StageStarted, ToolCompleted, SessionPaused)
- RouterPanel: new TUI widget rendering active session's lastResponseText
- TuiWsClient: remove println that was polluting the TUI on WS connect failure
2026-05-19 00:03:53 +04:00
kami 03615dc5b9 fix(server): wire tool registry and executor into OrchestratorEngines so LLM receives tool definitions 2026-05-18 22:03:31 +04:00
kami d2518849d7 fix(apps): send workflowId not path from CLI; wire sandboxRoot and systemPromptPath in server; update prompts and fixtures 2026-05-18 21:40:17 +04:00
kami 219e2c762e feat(cas): content-addressed artifact store (steps 1–8)
New core:artifacts-store interface + infrastructure/artifacts-cas
implementation: segment files + SQLite index, Blake3 hashing,
group-commit fsync via flushBefore, recovery tail-scan, manual
compactor, and oldest-first disk-cap evictor.

Inference events now carry promptArtifactId / responseArtifactId;
orchestrators put bytes before emitting. SqliteEventStore wraps
its txn in artifactStore.flushBefore so segment data is fsynced
before the event commit, making the crash window non-corrupting
(TailScanner re-indexes orphan tail records on reopen).

Compactor and evictor are mutually exclusive via maintenanceMutex.
Step 9 (cloud sync) deferred to a later epic.

See docs/reviews/2026-05-18-cas-steps-1-8-review.md for the final
review.
2026-05-18 12:22:38 +04:00
kami bbff73108e feat(server): wire log4j2 + log every event emission
Add log4j2/SLF4J deps and log4j2.xml, install Ktor CallLogging, replace
manual System.err.println sites with leveled loggers, and wrap the
EventStore with a LoggingEventStore decorator so every append/appendAll
is logged in one place.
2026-05-17 14:56:36 +04:00
kami 9b5e238820 fix(tui): run WS collectors on IO dispatcher so they aren't starved by runner.run 2026-05-17 14:25:36 +04:00
kami 46951ea896 style(tui): match epic-13 reference layout — titled panel blocks, status indicator, keybinds bar 2026-05-17 13:54:09 +04:00
kami b267982005 refactor(tui): migrate renderer from Mosaic to tamboui
Replaces the Mosaic 0.18 string-frame renderer with tamboui 0.2.1-SNAPSHOT
to unlock a cell buffer, widget catalog, and real layout engine. Domain
core (state/reducer/ws/input) is unchanged; only the renderer and the key
mapper are rewritten. Fixes a latent Mosaic-mapper bug where q/n/c/a/r/s//
were swallowed inside input modes by making the new mapper mode-aware.
2026-05-17 13:43:20 +04:00
kami 7d46f46f01 fix(server): event capturing and necessary logic for smoke test. 2026-05-17 03:21:42 +04:00
kami 0c1876a549 feat(tui): session filter + reconnect countdown
Tasks 4.2–4.3 of docs/plans/2026-05-17-tui-refactor.md:

- SessionList filters by workflowId (case-insensitive) using
  state.sessions.filter, populated by SubmitInput while in
  InputMode.Filter and cleared on CancelInput.
- TuiWsClient tracks reconnect attempt count and emits
  ConnectionEvent.RetryScheduled(attempt, nextRetryAtMs) before each
  backoff delay. Attempt resets on successful connect.
- StatusBar renders "reconnecting (attempt N, retry in Xs)" with
  recompose-driven countdown.

Also captures a renderer-evaluation note in the progress doc: Mosaic's
ceiling vs Textual, candidate JVM alternatives (tamboui, Kotter,
Lanterna, Mordant), and confirmation that the reducer/Effect core is
renderer-agnostic if a swap is ever pursued.

Pending: 4.1 (scroll log, deferred), 5.1 (coverage gate), 5.2 (cleanup).
2026-05-17 03:21:26 +04:00
kami b95135eb3b refactor(tui): event-loop foundation — actions, reducers, effects, Panel
Tasks 1.1–3.3 of docs/plans/2026-05-17-tui-refactor.md:

- Mosaic 0.13 → 0.18; Kotlin 2.0.21 → 2.2.10 (required by Mosaic).
  Fix MaxLineLength regressions in core/kernel orchestration logs.
- Input: drop raw System.in reader and ANSI escape parser. Wire
  Modifier.onKeyEvent at root; MosaicKeyMapper → KeyResolver → Action.
- State: split TuiState into Connection/Sessions/Input/Approval/Provider
  slices. Add InputMode.SteeringNote; delete handleSteer/System.console.
- Reducers: pure RootReducer composes slice reducers returning
  (state, List<Effect>). Effect is sealed (SendWs, Quit). Single
  dispatch(action) point in TuiApp; one coroutine drains effects.
- TuiWsClient now exposes messages/connection SharedFlows; suspend
  callbacks gone. ConnectionEvent sealed type added.
- Rendering: Panel(title){…} composable with LocalTerminalSize
  composition local; drop BOX_WIDTH and hand-padding from every
  component. Poll stty size every 500ms.
- Tests: KeyResolver (18) + 5 reducer suites (37). 55 total in :apps:tui.

Pending tasks 4.1–5.2 tracked in
docs/plans/2026-05-17-tui-refactor.progress.md.
2026-05-17 03:21:26 +04:00
kami f77efce10b debt(pre-router): resolved most of the technical debt that was noted while finishing epic-12 and epic-13. 2026-05-17 03:21:26 +04:00
kami 2207a37549 epic-13: add cli and tui entry point, finish epic. 2026-05-17 03:20:43 +04:00
kami c77277af0b epic-12: after epic audit and init commit 2026-05-17 03:19:39 +04:00