• v0.2.0 3b9c610587

    feat(cli,tui): issue #12 — presenter contract semantics amendment (v0.2.0)

    vh released this 2026-05-23 16:13:55 -07:00 | 266 commits to main since this release

    Replaces the stateless _render_event / _render_event_to_log helpers with
    stateful per-turn presenters (CliPresenterState / TuiPresenterState).
    Coalesces thinking-event deltas into a single growing display per run;
    demotes telemetry events with editorial hierarchy; formats duration +
    usage for human reading. Headline behavior change: a 50-token thinking
    phase now renders as ONE coalesced growing line in CLI (or one closed
    RichLog entry + per-delta live Static widget in TUI), not 50 lines of
    [thinking] spam.

    Editorial promotion line (issue #12 INV-002):

    • Load-bearing (no demotion prefix): Text, Done, Error, Cancelled
    • Demoted telemetry (. ASCII prefix in CLI; dim · in TUI):
      WorkerPhase, Thinking, TextBoundary, ToolStart, ToolResult

    Stateful coalescing:

    • Thinking deltas accumulate into thinking_buffer; first non-thinking
      event closes the run with a single \n boundary in CLI / one closed
      dim RichLog entry in TUI.
    • TUI adds a dedicated Static(id="thinking-current") widget that shows
      the last ~200 chars of the active run, mirroring per-delta updates.
      Two-views-of-thinking decoupling per INV-004: chronological RichLog +
      always-visible widget.
    • CLI INV-005: when stdout text was streamed mid-line,
      text_written_since_newline triggers a stdout flush + \n before the
      next stderr terminal label — guarantees [done] / [error] / [cancelled]
      land on their own line in a TTY without breaking pipe-to-file
      scripted consumers.

    Formatting helpers (issue #12 INV-006 / INV-007):

    • _format_duration_ms — autoscale 347ms / 5.5s / 1.2m
    • _format_usage — natural-language 6756 in -> 126 out (6882 total, 0 cached) with arrow="->" CLI / "→" TUI

    Cross-frontier design pass (eitri-smithy-dev, althing
    01KSBE52YZR5E3SPTKA672JE43) returned 16-of-16 confirmed decisions + 4
    material divergences applied:

    • ASCII . prefix in CLI (· is U+00B7, not ASCII)
    • RichLog one-closed-entry-per-run + Static per-delta updates (not
      inline-mirror as initially proposed)
    • presenter-state object instead of pure-function rendering
    • Framed as "contract semantics amendment", not "polish"

    Volva paraphrase round (5 prose-precision fixes applied to
    12.contract.md): INV-001 "growing display" semantics; single hide
    mechanism for the Static widget (Textual reactive display: bool);
    [render_error] security clause (type-only, no exception message);
    text_written_since_newline \n-terminated text corner case;
    [create_session] integration path (bypasses state.render — not an SSE
    Event variant).

    Volva code-review round (5 findings applied):

    • F1 drift: render-exception fallback now writes BOTH a plain-label
      fallback line for the original event AND the [render_error] <type>
      line (was missing the fallback half).
    • F2 drift: dim Rich style applied to all demoted-telemetry RichLog
      writes via rich.text.Text(..., style="dim") (was plain str).
    • F3 drift: belt-and-braces widget clear+hide on EVERY terminal event
      (Done/Error/Cancelled), even when thinking_open was False.
    • F4 precision: _format_usage gains PRE-001 assertion on the four
      expected usage keys.
    • F5 precision: _run_turn signature amended in issue #3 contract to
      document the new state: CliPresenterState | None = None test-
      injection kwarg.

    [create_session] lifecycle line demoted to . create_session: (written
    directly by _amain; bypasses state.render since it's not a wire-level
    SSE Event variant). Pre-amendment _render_event / _render_event_to_log
    and their test classes removed under the no-backwards-compat rule.

    Issues #3 and #4 contracts amended in-place: #3 (CliPresenterState
    CLASS + FN block + helper FN blocks + _run_turn signature + _amain
    create_session demotion); #4 (TuiPresenterState CLASS + FN block +
    compose Static widget + _stream_turn_worker state construction).

    209 tests GREEN; ruff clean. Bumps v0.1.0 → v0.2.0 (minor — output
    shape change breaks pre-amendment grep patterns like [thinking] ';
    no public API surface change beyond the rendering contract).

    Persistent-memory commit-along: captures the issue #12 decision,
    forward direction (require end_user_id for every access — declined
    worldtree-dev's requires_end_user_id offer because we'll send it
    universally), and the Heimdall scope-model foot-gun note (the
    "per-Tier-1-agent scope add" diagnosis was a phantom ask resolved by
    worldtree-dev's correction; agent.call:* baseline covers all Tier 1).

    Downloads