-
Notifications
You must be signed in to change notification settings - Fork 0
feat: cycle random quotes in TUI status bar and Web top bar #32
Description
Summary
Surface random quotes from the user's memory in idle UI real estate. Quotes are half the system's persistent memory — they should be visible somewhere other than a dedicated view.
Motivation
After running a full quote backfill migration (see v0.5.1 release), the system has 3,166+ quotes with correct speaker and channel attribution. These are rich, personal, often funny records of real conversations. They deserve passive visibility.
Design
Web — top bar empty space
Current layout:
|SidePanel| Chat with [persona] [tons of empty space] () Ready [Pause] [Menu]
Use the empty space for a slow vertical marquee (teleprompter-style scroll, ~20px/s) showing 2 lines of text. Quote text scrolls up continuously, pauses on hover. Small font, subdued color — doesn't compete with the persona name.
TUI — status bar
Current layout:
Ei [tons of whitespace] [Input] Ready
Single line, limited width. Use paginated scrolling:
- Word-wrap quote text to actual bar width
- Show each "page" for 30 seconds
- Advance to next page, then cycle to next quote after a few minutes
- Yield to real status info — if queue is active or something needs attention, suppress the quote
Both
- Cycle to a new random quote every ~3-5 minutes (configurable)
- Only show when idle
- Empty state: show nothing (no quotes yet = new user, don't fake it)
Attribution Format
— Sisyphus (persona said it, 1:1)
— Flare w/ Sisyphus (human said it, 1:1)
— Flare w/ Co-Creators (human said it, room)
— Beta and Lena (persona said it, room — channel name IS the room)
Logic (both fields now exist on every Quote as of v0.5.1):
speaker === "human"→— Flare w/ {quote.channel}speaker !== "human"ANDchannel !== speaker→ persona in a room →— {speaker} in {channel}(or just— {channel})speaker !== "human"ANDchannel === speaker→ 1:1 →— {speaker}channelis undefined (pre-v0.5.1 quotes that missed backfill) → omit attribution entirely, just show the text
Data
Quote shape (as of v0.5.1):
{
text: string;
speaker: "human" | string; // who said it
channel?: string; // where it was said (persona name or room name)
// ...
}Processor already has searchHumanData() which does semantic search. For random quote cycling, a simple random sample from state.human.quotes filtered by text.length > 20 (avoid noise) is sufficient — no semantic search needed.
Implementation Notes
- Quote fetch should happen on a timer in the frontend (not the Processor loop)
- TUI: read bar width from layout at render time for word-wrap
- Web: CSS
overflow: hidden+ CSS animation for the marquee — no JS scroll loop needed - Consider a
max_display_lengthcap (~300 chars) to avoid very long quotes dominating
Out of Scope
- Quote pinning / favoriting
- Filtering by persona or channel
- Click-to-view-full-quote
Related
- v0.5.1 — added
channelfield to Quote, fixedspeakerfor room messages - Issue Rename ExtractionContext.personaDisplayName → channelDisplayName #31 — rename
ExtractionContext.personaDisplayName→channelDisplayName(low priority, same concept)