docs(ui): classify App-resident runtime/derived fields (improvise-99k)

Step 4 of vb4. After steps 1–3, App owns model_state, view_state, and a
residue of five fields that don't belong to either slice. Add a top-level
doc on App explaining the slice structure and tag each residue field as
derived cache / runtime metadata / transient / config with a one-line
rationale. No behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Edward Langley
2026-04-29 17:33:27 -07:00
parent 9ad8abd8a5
commit 7249facf94
+36 -8
View File
@@ -271,22 +271,50 @@ impl Default for ViewState {
} }
} }
/// Top-level TUI application state. Composed of two named slices and a
/// residue of fields that don't belong to either:
///
/// - `model_state` — document state (Workbook + IO bookkeeping). Persists.
/// - `view_state` — UI session state (mode, cursors, panels, buffers, …).
/// Does not persist.
/// - The remaining direct fields are runtime / derived / config — see
/// per-field tags below. Each of them is documented as belonging to one
/// of these residue categories so the slice boundary stays explicit:
///
/// - **derived cache**: a pure function of the slices, recomputed on
/// demand. Owned by `App` because rebuilding belongs to the host.
/// - **runtime metadata**: data the runtime feeds in (terminal dims,
/// wall-clock instants). Not part of model or view state.
/// - **transient**: a flag whose lifetime is bounded to one method call
/// on `App`. Reset on entry, never observed across calls.
/// - **config**: data loaded once at startup and read but not written
/// during a session.
pub struct App { pub struct App {
pub model_state: ModelState, pub model_state: ModelState,
pub view_state: ViewState, pub view_state: ViewState,
/// **Runtime metadata**: wall-clock instant of the last autosave. Used
/// by `autosave_if_needed` to debounce writes. Not part of either slice
/// because it's about IO timing, not document or session state.
pub last_autosave: Instant, pub last_autosave: Instant,
/// Terminal dimensions (updated on resize and at startup). /// **Runtime metadata**: terminal dimensions, updated on resize events
/// and at startup. Fed in by the host loop in `draw.rs`.
pub term_width: u16, pub term_width: u16,
pub term_height: u16, pub term_height: u16,
/// Current grid layout, derived from model + view + drill_state. /// **Derived cache**: pure function of `model_state.workbook`,
/// Rebuilt via `rebuild_layout()` after state changes. /// `view_state.drill_state`, and the active view. Rebuilt via
/// `rebuild_layout()` after any state change. Owned by `App` because
/// it's the host's job to coordinate the rebuild, not the slices'.
pub layout: GridLayout, pub layout: GridLayout,
/// When set to true by an effect during `apply_effects`, the remaining /// **Transient**: when an effect sets this to `true` during
/// effects in the batch are skipped. The flag is reset at the start of /// `apply_effects`, the remaining effects in the batch are skipped.
/// every `apply_effects` call. Use via the `AbortChain` effect — this is /// Reset to `false` at the start of every `apply_effects` call. Use
/// the mechanism by which e.g. "advance at bottom-right" short-circuits /// via the `AbortChain` effect — this is the mechanism by which e.g.
/// the trailing `EnterEditAtCursor` in a `CommitAndAdvance` chain. /// "advance at bottom-right" short-circuits the trailing
/// `EnterEditAtCursor` in a `CommitAndAdvance` chain.
pub abort_effects: bool, pub abort_effects: bool,
/// **Config**: keymap configuration assembled at startup by
/// `KeymapSet::default_keymaps()`. Read every keypress but never
/// mutated during a session.
keymap_set: KeymapSet, keymap_set: KeymapSet,
} }