From 1e8a5e08ed561dfc4e9a63aa5abb6d81972531b6 Mon Sep 17 00:00:00 2001 From: vikingowl Date: Sat, 18 Oct 2025 03:20:32 +0200 Subject: [PATCH] docs(tui): MVU migration guide + module map --- docs/architecture.md | 2 +- docs/tui-mvu-migration.md | 109 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 docs/tui-mvu-migration.md diff --git a/docs/architecture.md b/docs/architecture.md index 2b94a85..e5bbf21 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -175,4 +175,4 @@ The TUI is rendered on each iteration of the main application loop in `owlen-tui 4. **State-Driven Rendering**: Each rendering function takes the current application state as an argument. It uses this state to decide what and how to render. For example, the border color of a panel might change if it is focused. 5. **Buffer and Diff**: `ratatui` does not draw directly to the terminal. Instead, it renders the widgets to an in-memory buffer. It then compares this buffer to the previous buffer and only sends the necessary changes to the terminal. This is highly efficient and prevents flickering. -The command palette and other modal helpers expose lightweight state structs in `owlen_tui::state`. These components keep business logic (suggestion filtering, selection state, etc.) independent from rendering, which in turn makes them straightforward to unit test. +The command palette and other modal helpers expose lightweight state structs in `owlen_tui::state`. These components keep business logic (suggestion filtering, selection state, etc.) independent from rendering, which in turn makes them straightforward to unit test. The ongoing migration of more features into the `Model–View–Update` core is documented in [`docs/tui-mvu-migration.md`](tui-mvu-migration.md). diff --git a/docs/tui-mvu-migration.md b/docs/tui-mvu-migration.md new file mode 100644 index 0000000..1d0790f --- /dev/null +++ b/docs/tui-mvu-migration.md @@ -0,0 +1,109 @@ +# TUI MVU Migration Guide + +This guide explains how we are migrating the Owlen terminal UI to a predictable **Model–View–Update (MVU)** architecture. Use it to understand the current layout, decide where new logic belongs, and track which features have already moved to the MVU core. + +--- + +## Goals + +- Make UI state transitions pure and testable. +- Reduce duplicated control flow inside `chat_app.rs`. +- Keep rendering functions dumb; they should depend on read-only view models. +- Ensure new features land in MVU-first form so the imperative paths shrink over time. + +Adopt the checklist below whenever you touch a feature that still lives in the imperative code path. + +--- + +## Module Map (owlen-tui) + +| Area | Path | Responsibility | MVU Status | +| --- | --- | --- | --- | +| Core state | `src/app/mvu.rs` | Shared `AppModel`, `AppEvent`, `AppEffect` definitions | **Ready** – composer + consent events implemented | +| Legacy app | `src/chat_app.rs` | Orchestrates IO, manages pending tasks, renders via ratatui | **Transitioning** – increasingly delegates to MVU | +| Event loop | `src/app/handler.rs` | Converts session messages into app updates | Needs cleanup once message flow is MVU aware | +| Rendering | `src/ui.rs` + `src/widgets/*` | Pure rendering helpers that pull data from `ChatApp` | Already read-only; keep that invariant | +| Commands | `src/commands/*` | Keymap and palette command registry | Candidate for MVU once palette state migrates | +| Shared state | `src/state/*` | Small state helpers (command palette, file tree, etc.) | Each module can become an MVU sub-model | + +Use the table to find the right starting point before adding new events. + +--- + +## Event Taxonomy + +Current events live in `app/mvu.rs`. + +- `AppEvent::Composer` – covers draft changes, mode switches, submissions. +- `AppEvent::ToolPermission` – bridges consent dialog choices back to the controller. + +`AppEffect` represents side effects the imperative shell must execute: + +- `SetStatus` – surface validation failures. +- `RequestSubmit` – hand control back to the async send pipeline. +- `ResolveToolConsent` – notify the session controller of user decisions. + +### Adding a new feature + +1. Extend `AppModel` with the new view state. +2. Create a dedicated event enum (e.g. `PaletteEvent`) and nest it under `AppEvent`. +3. Add pure update logic that mutates the model and returns zero or more effects. +4. Handle emitted effects inside `ChatApp::handle_app_effects`. + +Keep the event names UI-centric. Provider-side actions should remain in `owlen-core`. + +--- + +## Feature Migration Checklist + +| Feature | Scope | MVU tasks | Status | +| --- | --- | --- | --- | +| Composer (input buffer) | Draft text, submission workflow | ✅ `ComposerModel`, `ComposerEvent`, `SubmissionOutcome` | ✅ Complete | +| Tool consent dialog | Approval / denial flow | ✅ `AppEvent::ToolPermission`, `AppEffect::ResolveToolConsent` | ✅ Complete | +| Chat timeline | Message ordering, cursor, scrollback | Model struct for timeline + events for history updates | ☐ TODO | +| Thinking pane | Agent reasoning text, auto-scroll | Model + event to toggle visibility and append lines | ☐ TODO | +| Model picker | Filters, search, selection | Convert `ModelSelectorItem` list + search metadata into MVU | ☐ TODO | +| Command palette | Suggestions, history, apply actions | Move palette state into `AppModel` and surface events | ☐ TODO | +| File workspace | Pane layout, file tree focus | Represent pane tree in MVU, drive focus + resize events | ☐ TODO | +| Toasts & status bar | Transient notifications | Consider MVU-managed queue with explicit events | ☐ TODO | + +When you pick up one of the TODO rows, document the plan in the PR description and link back to this table. + +--- + +## Migration Playbook + +1. **Inventory state** – list every field in `ChatApp` that your feature touches. +2. **Define view model** – move the persistent state into `AppModel` (or a new sub-struct). +3. **Write events** – describe all user intents and background updates as `AppEvent` variants. +4. **Translate side effects** – whenever the update logic needs to call into async code, emit an `AppEffect`. Handle it inside `handle_app_effects`. +5. **Refactor call sites** – replace direct mutations with `apply_app_event` calls. +6. **Write tests** – cover the pure update function with table-driven unit tests. +7. **Remove duplicates** – once the MVU path handles everything, delete the legacy branch in `chat_app.rs`. + +This flow keeps commits reviewable and avoids breaking the live UI during migration. + +--- + +## Testing Guidance + +- **Unit tests** – cover the pure update functions inside `app/mvu.rs`. +- **Integration tests** – add scenarios to `crates/owlen-tui/tests/agent_flow_ui.rs` when side effects change. +- **Golden behaviour** – ensure the ratatui renderers still consume read-only data; add lightweight snapshot tests if needed. +- **Manual verification** – run `cargo run -p owlen-cli -- --help` to open the TUI and confirm the migrated feature behaves as expected. + +Every new MVU feature should land with unit tests plus a note about manual validation. + +--- + +## Tracking TODOs + +- Keep this file up to date when you migrate a feature. +- Add inline `// TODO(mvu)` tags in code with a short description so they are easy to grep. +- Use the `docs/` folder for design notes; avoid long comment blocks inside the code. + +Future contributors should be able to glance at this document, see what is done, and understand where to continue the migration. + +--- + +Questions? Reach out in the Owlen discussion board or drop a note in the relevant PR thread. Consistent updates here will keep MVU adoption predictable for everyone.