Files
owlen/docs/tui-mvu-migration.md

110 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.