A design pass through /frontend-design on the web companion to retain all debugging richness while raising usability and polish. Single-file vanilla HTML/CSS/JS; no build, no CDN, no node_modules. HTTP surface, endpoints, presentation contract, and INV-001..009 all unchanged. Aesthetic direction: "Aurora telemetry instrument." - Runic glyph + wordmark, live connection dot (idle = aurora-green, streaming = pulsing cyan, error = dawn-red), session identity right- aligned. Persona summary lives inline in the top bar with labeled P/A/D micro-bars (centered baseline, [-1,1] mapped). - Aurora signature band — thin cyan→blue→green shimmer animation at the top edge, echoed on the setup card. - Conversation column with turn-divider rules, cyan ❯ prompt echoes, assistant text with a live cyan left-rule. Terminal events become status chips (done = aurora-green, error = dawn-red, cancelled = dawn-yellow) with metadata. Animated "awaiting first token · Ns" indicator with elapsed counter. - Telemetry column: tabs with live count badges that flash on new events, sticky pane header carries the active pane name + copy button, new-line flash highlight on each pane append, structured empty states, persona pane structured render. - Composer: real input, send/cancel buttons, streaming-lock state. - Status line: keyboard legend + version footer. - Centered setup card overlay with styled agent select on first open. - All-monospace by intent (no-CDN constraint + right for a wire- monitor tool); system mono stack. CSS-only motion (pulse, shimmer, staggered rise, flash, awaiting dots). Live Markdown — transcript response + thinking panes: - Hand-rolled markdownSafe() renderer: escape-FIRST (INV-004 preserved), then a whitelist subset (headings, bold, italic, inline code, fenced code blocks, ordered/unordered lists, blockquotes, links). No raw HTML passthrough. Link href restricted to http(s):// + conservative charset (rejects javascript:, attribute-breakout URLs). - Per-turn live buffer; each text/thinking delta re-renders the accumulated buffer in place (same pattern as the TUI's v0.9.0 live MD rendering). - Verified under node: rendering (bold/italic/code/lists/headings/ fences/safe links) + XSS neutralization (script tags, javascript: schemes, attribute-breakout URLs, img onerror) all behave correctly. - Tools/Debug/Persona panes stay literal monospace by deliberate choice: they carry our structured audit lines + JSON, where MD would corrupt readability (underscores in tool names, JSON braces, etc.). Thinking pane per-turn breaks: - Each turn lays down a labeled `── turn N ──` divider in the thinking pane. The prior turn's live block is closed and a fresh MD-rendered block opens below the divider, so each turn's chain- of-thought is its own break-separated section. Tests: 378 passing (no test change — server-side surface unchanged). Markdown safety verified via standalone node harness exercising rendering + 4 XSS vectors. Minor per SemVer discipline: substantial new browser-side behavior (live Markdown rendering, redesigned presentation) that consumers would opt into via the next launch. No HTTP-caller adapts.
Ratatoskr
A Worldtree Conversation API debug TUI. Runs up and down Worldtree's API surface — sessions, turns, persona, tools, admin events, Bifrost state — carrying messages between layers. Like the squirrel.
The product is the observability surface; chat is the input mechanism. Devs run Ratatoskr against a local Worldtree to watch a turn flow through every layer of the system, side-by-side, in one terminal.
Status
v0 scaffold. Design locked; implementation hasn't started. The dev team owns the implementation pass.
Read in this order
docs/design-brief.md— the locked design. Read this first. Every architectural decision is recorded with its rationale, the alternatives considered, and (where relevant) the operator's lock-in moment.docs/SPEC-PIN.md— what Worldtree spec version Ratatoskr is built against, where the vendored snapshot lives, and how to bump the pin.docs/conversation-api-spec.md— the vendored Worldtree spec snapshot. Read this to understand the API surface Ratatoskr consumes. Do not import anything from a Worldtree checkout — the boundary is the spec, not the code. Seedocs/design-brief.md§2.CLAUDE.md— Claude Code conventions for this repo (mostly inherited from the Corviduo template).persistent-memory.md— durable intent across context resets. Update as decisions and state evolve.
Quickstart
# 1. Environment
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
# 2. Verify the spec pin
cat docs/SPEC-PIN.md # documented Worldtree SHA + bump procedure
# 3. Tests (none yet; scaffold only)
uv run pytest
# 4. Run against a local Worldtree (once implementation lands)
# Worldtree must be running: python -m core.conversation_api
ratatoskr --agent mimir
What this repo is NOT
- NOT a polished consumer for Worldtree's end-users — that's the web app.
- NOT a Worldtree admin tool — admin CLI is separate (
sessions_cli.pylives in Worldtree). - NOT a featuretracking shadow of the web app — when the Conversation API surface grows, Ratatoskr does not necessarily grow with it.
- NOT a remote-Worldtree debug client — file-tail surfaces (persona log, server log) assume local-dev posture.
The full negative-clause list lives in docs/design-brief.md §6.
Boundary rule
Ratatoskr depends on three things only:
httpx+httpx-sse(network layer)textual(TUI framework)- Worldtree's published Conversation API spec at the pinned SHA
Hard rule: no imports from a Worldtree checkout. No core.* imports,
no from worldtree.*, no shared models, no submodule of Worldtree. The
spec is the entire surface. Boundary smoke test at tests/test_no_worldtree_imports.py
enforces this in CI.
Version-skew strategy
The dev team is decoupled from Worldtree's dev team. To detect drift when Worldtree changes the API:
- Spec-version pin in
pyproject.toml(worldtree-spec-rev). Bump explicitly; bumps are a tracked action. - Recorded-SSE snapshot tests at
tests/snapshots/. Captured against a live Worldtree; replayed in CI. Re-record after every pin bump. - Conformance smoke test — boots Worldtree via Docker compose in CI, runs a one-turn happy path. Catches integration-level drift.
See docs/SPEC-PIN.md for the bump procedure.
Consumer-side discoveries
If you find a spec gap, ambiguity, or missing-but-needed endpoint while working on Ratatoskr: route the discovery back to worldtree-dev via althing rather than via PR on Worldtree directly. The separate-team boundary is intentional and helps catch spec gaps that an in-tree consumer would paper over.
Related repos
- Worldtree — the API Ratatoskr consumes
- brokkr-smithy — authored this design brief
- Skaldsong — another Worldtree API consumer (Python; render-and-aggregate pattern)
- mead-hall — another Worldtree API consumer (TypeScript; server-side broker)