docs: add module documentation in AsciiDoc with PlantUML diagrams
Generated by per-group subagents covering all 52 modules across: core (18), infrastructure (10), apps (5), interfaces (3), plugins (7), testing (9) Documentation format: - AsciiDoc (.adoc) files in docs/modules/<group>/ - PlantUML (.puml) files in docs/diagrams/ - .adoc files reference diagrams via include:: directives Each doc covers: purpose, responsibilities, non-responsibilities, key types, event flow, integration points, invariants, PlantUML diagram, known issues, and open questions.
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
= app-tui
|
||||
|
||||
== purpose
|
||||
|
||||
Terminal UI built on the Tamboulib TUI framework that provides a real-time interactive dashboard for monitoring and controlling Correx sessions.
|
||||
|
||||
== responsibilities
|
||||
|
||||
* Display a live session list with status, workflow name, and background-update badges
|
||||
* Show workflow definitions available on the server for starting new sessions
|
||||
* Stream session lifecycle events (stage, tool, inference) in a scrollable event strip
|
||||
* Display tool diffs when tool executions complete with file modifications
|
||||
* Surface approval requests with tool name, tier, risk summary, and command preview
|
||||
* Accept approval decisions (approve / reject) and steering notes via keyboard input
|
||||
* Support session filtering by workflow name, input history navigation, and keyboard-driven UI modes
|
||||
|
||||
== non-responsibilities
|
||||
|
||||
* Does not contain any domain orchestration or event-sourcing logic
|
||||
* Does not persist any state — all state is in-memory and rebuilt on reconnect
|
||||
* Does not authenticate or encrypt connections
|
||||
* Does not support mouse interaction
|
||||
|
||||
== key types
|
||||
|
||||
=== TuiState
|
||||
* **kind**: data class
|
||||
* **purpose**: Root application state. Contains `connection`, `sessions`, `input`, `provider` sub-states plus display metadata (cursor position, input buffer, history, snapshot phase flags, per-session cursors).
|
||||
|
||||
=== SessionsState
|
||||
* **kind**: data class
|
||||
* **purpose**: Holds the list of `SessionSummary` objects, filter text, session/workflow selection, and background update counter.
|
||||
|
||||
=== DisplayState
|
||||
* **kind**: enum
|
||||
* **purpose**: Tri-state enum (`IDLE`, `IN_SESSION`, `APPROVAL`) that drives which layout the TUI renders.
|
||||
|
||||
=== SessionSummary
|
||||
* **kind**: data class
|
||||
* **purpose**: Projected view of a session for display — ID, status, workflow, stage, tools, recent events, pending approval.
|
||||
|
||||
=== TuiWsClient
|
||||
* **kind**: class
|
||||
* **purpose**: Ktor WebSocket client that maintains a persistent global stream (`/stream`). Exposes cold `Flow<ServerMessage>` and `Flow<ConnectionEvent>` backed by `Channel.UNLIMITED`. Implements exponential backoff reconnection.
|
||||
|
||||
=== Action (sealed interface)
|
||||
* **kind**: sealed interface
|
||||
* **purpose**: Union of all user input and system events (navigation, input editing, approval, server messages, connection events).
|
||||
|
||||
=== KeyEvent (sealed class)
|
||||
* **kind**: sealed class
|
||||
* **purpose**: Normalized key events independent of the TUI backend (TambouiKeyEvent mapping).
|
||||
|
||||
=== RootReducer
|
||||
* **kind**: object
|
||||
* **purpose**: Top-level reducer that coordinates `SnapshotPhaseReducer` + four sub-reducers (`InputReducer`, `SessionsReducer`, `ConnectionReducer`, `ProviderReducer`). Handles cross-reducer state weaving (input history, approval dismissal, auto-enter on session start).
|
||||
|
||||
=== SnapshotPhaseReducer
|
||||
* **kind**: object
|
||||
* **purpose**: Manages the snapshot-to-live transition. Buffers event-bearing messages during snapshot replay; drains buffered events atomically when `SnapshotComplete` arrives; deduplicates live events by `sessionSequence`.
|
||||
|
||||
=== Effect (sealed interface)
|
||||
* **kind**: sealed interface
|
||||
* **purpose**: Side-effect descriptors produced by reducers — either `SendWs(ClientMessage)` or `Quit`.
|
||||
|
||||
=== EffectDispatcher
|
||||
* **kind**: class
|
||||
* **purpose**: Executes effects sequentially. Dispatches WS messages via `TuiWsClient.send()` and `Quit` via a callback that exits the TUI runner.
|
||||
|
||||
== event flow
|
||||
|
||||
*inbound:* `ServerMessage` frames from the global WebSocket stream, decoded by `TuiWsClient` and wrapped in `Action.ServerEventReceived`. Also connection lifecycle events (`Connected`, `Disconnected`, `RetryScheduled`).
|
||||
|
||||
*outbound:* `ClientMessage` frames sent via `Effect.SendWs` — `StartSession`, `CancelSession`, `ApprovalResponse`.
|
||||
|
||||
== integration points
|
||||
|
||||
* `:apps:server` — imports `ServerMessage`, `ClientMessage`, `ApprovalDecision`, `PauseReason`, `WorkflowDto`, `ProviderHealthDto`
|
||||
* `:core:events` — imports `ApprovalRequestId`, `SessionId`
|
||||
* `:core:approvals` — imports `Tier`
|
||||
|
||||
Tamboulib framework: `tamboui-tui`, `tamboui-widgets`, `tamboui-core`, `tamboui-jline3-backend`.
|
||||
|
||||
== invariants
|
||||
|
||||
* `ws.messages` and `ws.connection` are single-consumer cold flows — adding a second collector drops messages from one
|
||||
* Effects are dispatched sequentially (dispatchAll) — order matches `RootReducer` concatenation
|
||||
* `Effect.Quit` is always appended last by `RootReducer.reduce`
|
||||
* Snapshot phase is entered initially and on every `Disconnected`; buffered events are drained atomically at `SnapshotComplete`
|
||||
* Live event deduplication uses per-session `sessionSequence` cursor; gaps are warned and applied anyway
|
||||
* The TUI creates one WS connection (`/stream`) — per-session streams are not used
|
||||
|
||||
== PlantUML diagram
|
||||
|
||||
[plantuml, app-tui, "png"]
|
||||
----
|
||||
include::../../diagrams/app-tui.puml[]
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
||||
== known issues
|
||||
|
||||
* `StageToolManifest` arriving before `SessionStarted` is silently dropped (TODO RF-3) — the session won't exist in the list yet
|
||||
* Chat submission in `IN_SESSION` is blocked (returns empty effects) — router integration is deferred to Epic 14
|
||||
* `InputHistory` limit is hardcoded to 50 entries per session
|
||||
* Event strip shows at most 5 events for the selected session
|
||||
* Session list is capped at 7 visible entries; overflow is shown as a count but not scrollable
|
||||
|
||||
== open questions
|
||||
|
||||
* Should the TUI support per-session WebSocket streams instead of relying solely on the global stream?
|
||||
* Should approval decisions support freeform steering note input that can exceed one line?
|
||||
* How should workflow picker handle very large numbers of available workflows (10+)?
|
||||
Reference in New Issue
Block a user