docs(tui): MVU migration guide + module map

This commit is contained in:
2025-10-18 03:20:32 +02:00
parent 218ebbf32f
commit 1e8a5e08ed
2 changed files with 110 additions and 1 deletions

View File

@@ -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 `ModelViewUpdate` core is documented in [`docs/tui-mvu-migration.md`](tui-mvu-migration.md).

109
docs/tui-mvu-migration.md Normal file
View File

@@ -0,0 +1,109 @@
# TUI MVU Migration Guide
This guide explains how we are migrating the Owlen terminal UI to a predictable **ModelViewUpdate (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.