• v0.4.0 24e4371ec7

    feat(tui): issue #13 — §5 layout reshape + Tools pane (v0.4.0)

    vh released this 2026-05-23 21:41:16 -07:00 | 262 commits to main since this release

    Reshape the TUI from vertical-stack single-pane to Horizontal
    two-column with TabbedContent on the right; v1 has a single Tools
    tab that consumes ToolStart/ToolResult SSE events previously
    rendered inline in the transcript. Foundation for the rest of
    design-brief §5; subsequent panes (Persona/AdminEvents/BifrostState/
    ServerLog) plug in as sibling TabPanes when their substrate
    blockers resolve.

    Three coupled pieces, all in-place amendments to issues #4 + #12:

    • Layout: compose() yields Horizontal#main-row containing
      Vertical#left-column (transcript + thinking-current + prompt) and
      Vertical#right-column (TabbedContent#side-panes with
      TabPane#tools-tab → RichLog#tools-log). Width split 2fr:1fr. CSS
      dock rules narrow to per-container scope so thinking-current
      toggling doesn't reflow the right column.
    • Tools pane: TuiPresenterState.render() signature widens with
      tools_log: RichLog. ToolStart/ToolResult route there per INV-014;
      every other event keeps its issue-#12 routing. Plain-label
      fallback under render-exception preserves routing (INV-009).
    • Ctrl+1 binding + pane-name widget: BINDINGS gains
      Binding("ctrl+1", "focus_tools") which programmatically sets
      TabbedContent.active; Textual's default preserves Input focus per
      INV-016 (test asserts; regression path documented).
      Static#pane-name in the footer renders "Tools" v1 (static — no
      tab-switch handler wiring lands in #13 per amendment-2 from
      Volva paraphrase review).

    CLI mode (--send) is unaffected by design per INV-018 — non-
    interactive, no tabs concept; CLI keeps inline tool-event rendering.

    Contract: docs/contracts/issues/13.contract.md (drift-check clean,
    two amendments applied from Volva contract-paraphrase pass).

    Tests: +9 net (TestLayoutShape × 7 + TestTuiPresenterState routing
    × 3, minus 1 deprecated test_tool_start_demoted superseded by
    test_tool_start_routes_to_tools_log). 236 total GREEN; ruff clean.

    Live smoke against personal Worldtree's mimir: tool-using turn
    (KB search) populated tools_log with tool_start + tool_result for
    search_library + read_note; transcript stayed chat-only with
    worker_phase + thinking. Routing-not-duplication confirmed
    end-to-end.

    Downloads