-
feat(tui): persona surface — sticky header + TabPane (v0.13.0)
released this
2026-05-25 19:13:47 -07:00 | 242 commits to main since this releaseStep 3 of the Worldtree #204 integration: visible persona-state UX.
Pairs with v0.11.0's AffectUpdate SSE event + v0.12.0's
get_persona_state HTTP client — together those gave the data; this
bump surfaces it.Two surfaces (Option C: both):
Sticky persona-header (top of screen, dock=top, height=1):
- Shape:
agent_id · dominant_emotion · pad(P, A, D) · N emotions active— concise enough for at-a-glance scan above the chat - Starts hidden via
.emptyCSS class; height collapses to 0 when
the agent has no persona surface - Refreshes on AffectUpdate(status="current") snapshots
Persona TabPane (Ctrl+4):
- Full snapshot detail: dominant emotion, PAD axes with baseline +
delta, mood drift, active emotions with intensity + decay
(minutes-rounded), last_updated_at footer - Replaced (not appended) on each new snapshot — snapshots are
absolute state, not incremental
Lifecycle:
- on_mount spawns a Textual worker that calls get_persona_state to
hydrate header + pane before turn 1 - PersonaNotConfigured (domari, muninn, Tier 3) → pane carries an
italic placeholder, header stays empty - AgentNotAvailable / AuthScopeDenied / network error → italic
failure placeholder; audit-logged; never crashes - Presenter's render() takes an optional
on_persona_snapshot
callback so AffectUpdate(current) refreshes both surfaces during
a live turn (no widget coupling — App owns the callback)
Tests: 10 new (4 formatters, 3 presenter callback, 4 layout/binding/
hydration). Full suite: 313 passing.Downloads
- Shape: