TUI layout reshape + Tools pane (§5 v1 entry point) #13
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Today's TUI is a single-pane vertical stack:
This shape was correct for v0.x's chat-only scope. Design-brief §5 commits ratatoskr's actual product surface to a multi-pane debug-observability dashboard:
§5 is the biggest reshape since v0.1.0. Most panes are blocked on substrate that isn't here yet:
/persona/logendpoint (weeks of cross-repo work)admin.events.readscope (issue #11)/admin/sessions/{id}/bifrostToolStart/ToolResultSSE eventsHorizontal2-col +TabbedContentchrome)The realistic §5 entry point is layout refactor + Tools pane together: both unblocked, both compose, together they ship the multi-pane shape the design brief commits to without depending on cross-repo or scope-grant work first.
Solution
One in-place amendment to issue #4 (
ratatoskr.tui). Three coupled pieces:Layout reshape
RatatoskrApp.compose()shifts from vertical-stack toHorizontaltwo-column:The vertical-stack DEFAULT_CSS (
dock: top/dock: bottom) gets reshaped around the new Horizontal parent. Width split ~2:1 (chat is primary).Tools pane
Routes
ToolStart/ToolResultSSE events from the main transcript to a dedicatedtools_log: RichLogin the right column's first tab. The current presenter (TuiPresenterState) treats these as demoted telemetry (· tool_start: …/· tool_result: …inline); post-amendment they go to the pane instead.Rationale: per design-brief §5 "side pane (inline-from-SSE for v1)" — the events are routed, not duplicated. The main transcript becomes cleaner (chat is chat; tool activity is the pane); the Tools pane gains independent scrollback for long tool-call sequences.
CLI mode is unaffected —
--sendis non-interactive, no tabs concept; CLI keeps its current inline tool-event rendering.Status footer
Current footer has
identity(agent_id · …session_id_tail) +hint(Ctrl-C state). §5 adds a current-pane-name indicator. v1 only has one tab (Tools) so the indicator is fixed; it extends naturally as panes are added.Keybindings
Ctrl+1activates the Tools tab without stealing input focus. v1 has just one tab; bindings extend toCtrl+2..5as Persona/AdminEvents/BifrostState/ServerLog land. Input field retains keyboard focus across tab switches (the design brief's "without losing focus on the input field" invariant).Out of scope (this issue)
--server-logflag.{!r:.200}truncate behavior stays; smart truncation is its own concern.Acceptance
docs/contracts/issues/13.contract.md(amends #4) drift-checks clean.Ctrl+1switches tab without focus loss, identity widget still renders, single-turn smoke through the new layout.uv run ruff check src/ tests/clean.ratatoskr --new): picker → mimir → chat pane is left column, Tools pane is right column, type a message, tool-using turn (e.g. ask Mimir to search the KB) → tool events render in the right pane, model text renders in the left transcript.Dependencies
ratatoskr.tui) — landed; this issue is an in-place amendment.render().Shipped at
24e4371(v0.4.0).TUI reshaped to Horizontal two-column per design-brief §5. Left column = chat surface; right column = TabbedContent with Tools tab. ToolStart/ToolResult route to the Tools pane (INV-014); routing-not-duplication confirmed via live smoke against personal Worldtree (mimir KB search populated tools_log with search_library + read_note events; transcript stayed chat-only).
Surface added:
TuiPresenterState.render()widened to taketools_log: RichLog.RatatoskrApp.action_focus_tools+Ctrl+1binding.Static#pane-namefooter element (renders "Tools" v1; dynamic when more tabs land — no handler wiring lands in this issue per Volva amendment).Contract:
docs/contracts/issues/13.contract.md— drift-check clean, two amendments from Völva contract-paraphrase pass applied (Input-focus invariant priority over assumption; pane-name handler-wiring explicit deferral).Tests: +9 net; 236/236 GREEN; ruff clean.
Follow-ups unblocked by this foundation:
/persona/logendpoint if needed.admin.events.readscope).