# Design brief — `ratatoskr-web` (Worldtree wire monitor)

> **For:** a visual design pass (Claude Design). **Deliverable:** a single
> self-contained HTML prototype, fully populated with representative static
> data, that an engineer will wire live data into. **Do not** build a data
> layer — build the *shell* and *every state*, beautifully, with placeholder
> content in every slot.

---

## 1. What you're designing

`ratatoskr-web` is a **developer-grade debug/observability console** for a
conversational-AI engine (Worldtree). Its tagline is *"wire monitor"*: you open
a session with an AI agent, send it turns, and **watch that turn flow through
every layer of the system at once** — the streaming response, the model's
chain-of-thought, the tools it can call, the agent's live emotional/persona
state, the provider handshake, and the engine's admin lifecycle events — all
side-by-side on one screen.

**The product IS the observability surface. Chat is just the input.** This is
not a chat app, not a marketing page, not an end-user product. The user is one
developer (occasionally a few LAN peers) staring at a dense instrument to debug
what the engine is doing. Think **oscilloscope / flight-data console / a well-lit
`htop`**, not a messaging UI.

**Design values, in priority order:**
1. **Information density earns the screen.** Every region shows live, changing
   data. Nothing is decorative filler. A quiet, legible, glanceable density is
   the whole point — the user reads six data streams at a glance.
2. **Calm under motion.** Multiple regions update in real time (token streams,
   live metrics, event logs). The design must stay readable while things move —
   no jitter, no attention-grabbing per-item animation. Motion is for *state
   change*, used sparingly.
3. **Legibility first.** Monospace, high contrast where it counts, generous but
   not wasteful spacing. This runs for hours; it must not tire the eye.

---

## 2. Aesthetic direction — Australis

Use the **Australis design system** (a cool-toned, terminal-first dark theme —
the `australis-design` skill has the canonical tokens: colors, spacing, radii,
shadows, motion). Import/inline `colors_and_type.css`; don't reinvent tokens.

Non-negotiables from the brand:
- **Dark only.** Base is a cool near-black **`#222531` — never pure `#000`.**
  The eye rests in low-contrast cool grey; **emphasis comes from *brightness*,
  not saturation.** Layer surfaces up the Sea neutral ramp (`#222531 →
  `#373b46` → `#414751`).
- **Palette families:** *Ice* (surface neutrals), *Aurora* (blue → cyan → green,
  the primary accents — used generously in that preference order), *Dawn*
  (red/yellow/magenta — sparingly, for status only). Semantic: info=blue,
  success=green, warning=yellow, danger=red.
- **The signature motif is the aurora glow** — a low-opacity cyan→blue→green
  light coming *through* the top of the screen, plus a 3px aurora focus ring on
  interactive controls. Lean into this as the one memorable thing.
- **No noise, no textures, no patterns.** *"The screen is the polar sky — empty,
  with light coming through it."* The one sanctioned gradient is the aurora glow.
- **Never a colored left-border on cards** (the LLM-slop trope). Featured cards
  accent the *top* edge instead.
- **Type:** this instrument is **mono-first** — that IS on-brand for Australis
  ("terminal-first"). Use a monospace stack (JetBrains Mono / system mono; see
  §9 — no web-font CDN allowed). Eyebrows/labels are **mono, UPPERCASE, ~11px,
  wide-tracked (`0.08–0.16em`)** — use them liberally; they're a system
  signature.
- **Motion:** calm, never bouncy. ~120ms hover, ~200ms state, ~320ms panels.
  Focus = aurora glow ring. Hover = one step *brighter* (not lower opacity).
  A slow (8–14s) aurora drift on a hairline top band is welcome; nothing else
  should loop.

The current UI already borrows this palette — you're not inheriting it, you're
**redesigning the layout and craft from scratch** with the brand as the guide.
Feel free to rethink the spatial composition entirely (see §10).

---

## 3. The two screens

### Screen A — **Session setup** (entry)
A single centered card on the aurora canvas. Fields:
- **Agent** — a `<select>` (populated live; show 3–4 sample options incl.
  `ratatoskr:sindra`, `forseti`, `mimir`).
- **Bifrost binding (Tier-3 provider)** — a `<select>`: `combined (:8392)` /
  `none — observe only` / `memory (:8391)` / `affect (:8390)`.
- **Open session** — primary button.
- An error line (design the error state too — e.g. "agent not available").

### Screen B — **Live workspace** (the main event — 95% of the design effort)
Persistent top bar + status line spanning full width; between them a **two-region
body: a conversation column (left, dominant) and a telemetry column (right,
tabbed).** Current split is ~1.85 : 1 — you may re-proportion. The information
inventory below is exhaustive; **every item needs a home.**

---

## 4. THE COMPLETE INFORMATION INVENTORY

This is the core of the brief. Design a slot for **every** item, in a sensible
state. Data shapes are given so your placeholders read true.

### 4.1 Top bar (persistent)
| Item | Shape / example | Notes |
|---|---|---|
| Brand | `ᛯ ratatoskr` + eyebrow `WIRE MONITOR` | the mark is a rune glyph; small |
| **Connection status** | one of: `offline`, `connected` (idle), `streaming`, `error` | dot + label; **streaming pulses**; color-coded (grey/green/cyan/red) |
| **Persona strip** (appears after a session hydrates) | dominant-emotion word (`love`) + **PAD bars**: `P`, `A`, `D` | each PAD bar is **bipolar** — centered on 0, fills left (negative) or right (positive), value ∈ [−1, 1]; **live-updates every turn** |
| Session identity | `ratatoskr:sindra · …381b99f4` | agent id + last-8 of session id |
| Bound-plane badge (when bound) | `⇄ combined  http://10.100.10.50:8392` | plane + endpoint; only when a Bifrost binding is active |

### 4.2 Conversation column (the transcript + composer)
The transcript is a scrollable stream of turns. Design each element:

| Element | Example content | Notes |
|---|---|---|
| **Turn divider** | `TURN 3` between hairlines | uppercase eyebrow, rule lines each side |
| **User prompt echo** | `❯ what's your intensity setting?` | the user's message, accent-marked |
| **Assistant response** | streaming **Markdown** (headings, bold, italic, `code`, lists, quotes, links) | accumulates token-by-token while live; distinct "live" treatment vs settled |
| **Seeded first-message** | a full assistant turn present *before the user speaks* (an authored greeting) | renders **identical to a lived assistant turn** — the session can OPEN already showing the agent's opener |
| **Reasoning / "thinking" note** | `✦ sindra is reasoning···` (italic) | **ephemeral** app affordance — appears while the model reasons, vanishes the instant real text begins; visually distinct from the response so it never reads as engine output |
| **Awaiting-first-token** | `···` animated | heartbeat before the first token |
| **End-of-turn status chips** | `✓ DONE 1.84s` · `✗ ERROR agent_not_available` · `⚠ CANCELLED` · `✗ WIRE lost` | small bordered chips; color per state |
| **Composer** (pinned bottom) | `❯ [ message input ]  [SEND]` | Enter=send, Shift+Enter=newline; during a turn the Send button becomes **CANCEL** (amber) |

### 4.3 Telemetry column (six tabbed panes)
A tab bar + a pane header (with a **Copy** button) + the active pane body.

**Tabs** (each: name · keybinding hint · a count **badge** that *flashes* on new
data): `TOOLS ^1` · `DEBUG ^2` · `THINK ^3` · `PERSONA ^4` · `BIFROST ^5` ·
`ADMIN ^6`. Active tab is accent-marked.

Pane contents — design each, populated:

1. **Tools** — the tool inventory the model saw at turn-fire:
   `agent_id`, `builtin_tools[]` (names), `bifrost_tools[]` (name + description +
   parameters). Below it, **live tool-call events** stream in (`tool_start` →
   `tool_result`) as the turn runs. Empty state: `— live tool events —`.
2. **Debug** — a raw structured op/lifecycle log (mono lines; new lines flash
   once). Think `tail -f`.
3. **Think** — the model's **full chain-of-thought**, per-turn dividers,
   live-Markdown. Longer prose than the response.
4. **Persona / affect** — *the richest pane.* Contains:
   - **The canonical NL directive** the engine injects into the agent's context
     — the literal text: a **mood descriptor** ("neutral", "faintly excited",
     ±0.3 bands) + a **relationship directive**. Show this verbatim, quoted.
   - **PAD mood point** — pleasure / arousal / dominance current values.
   - **relations[]** — for each related entity (e.g. the user): **trust**
     (ability / benevolence / integrity), **warmth**, **agency**,
     `relation_context` (a tie-type word like "stranger" / "expressive"), each as
     a **metric row**: `label · value · Δ-since-last (▲/▼) · unicode sparkline ·
     n (evidence count) · descriptor`. Values are 0–1 with 2–3 decimals.
   - **dominant_emotion** (an OCC type: joy/anger/fear/…) + **emotions_active[]**.
   - Design the **metric row** as a reusable component — it's the densest,
     most-repeated element in the whole UI. Tabular-aligned numbers, a tiny
     inline sparkline, a subtle up/down Δ.
5. **Bifrost** — the live provider binding (admin-gated): `endpoint`,
   `connected` (bool), `capabilities_granted[]`, `consumer_id`, `tools[]`.
   **Self-labeling states:** `not configured` (no admin key) / `not bound`
   (session has no live binding) / an auth-denied state.
6. **Admin events** — a live event log of the engine's lifecycle broadcast
   (a ~17-type vocabulary: `turn.started`, `session.created`, `system.*`, …),
   filtered to the active session. Streaming; timestamped lines.

### 4.4 Status line (persistent, bottom)
- **Keybinding legend:** `Enter send · ⇧Enter newline · ^1–^6 panes · ^C cancel`
  (rendered as little `kbd` chips).
- **Version:** `ratatoskr 0.19.9` (right-aligned).

---

## 5. States to design (show these explicitly)

Provide a mock (or a toggle) for each — these are where debug UIs live or die:

- **Setup:** loading-agents · ready · create-error.
- **Connection:** offline · connected/idle · streaming (pulsing) · wire-error.
- **Turn lifecycle:** awaiting-first-token · reasoning (✦) · streaming response ·
  done (+timing chip) · error · cancelled.
- **Panes:** empty/placeholder · hydrated/dense · **not-configured** (admin key
  absent) · **not-bound** (Bifrost) · error · a **badge flash** on new data.
- **Persona pane specifically:** a fully-populated relations block AND a
  cold/empty one (a fresh agent with no accumulated state).

---

## 6. Interaction & motion

- **Real-time is the defining trait.** The response + thinking panes stream
  token-by-token; the metric rows tick; event logs append; the persona strip
  re-animates each turn. Design so all of this is *calm* — the reader's eye
  isn't yanked around. Reserve motion for genuine state transitions
  (turn-start, done, a new event) and keep it short.
- **Keyboard-first.** `^1–^6` switch panes; `Enter`/`⇧Enter`/`^C` drive the turn.
  Panes are also clickable. Show focus states.
- **The aurora glow is the interaction signature** — focus rings, the top band,
  the connection pulse, the primary-button hover. Make it the thing someone
  remembers.
- **Copy-to-clipboard** on each pane header (with a copied-confirm state).

---

## 7. Layout — you have latitude

The current layout is a fixed two-column split. **You may rethink it** — as long
as every §4 item has a legible home and the density stays high. Directions worth
exploring (pick one, commit):
- A **command-console** feel: a slim persistent left rail of "instruments," a
  dominant conversation center, a right telemetry stack.
- A **grid of live tiles** (the metrics/panes as a dashboard) with the
  conversation as the anchor column.
- The **classic monitor** split, but with far better hierarchy, grouping, and
  breathing room than today.

Desktop-first; design at **1440–1512px** wide. Graceful down to ~1100px is a
plus (this runs on a dev laptop). No mobile.

---

## 8. Deliverable — what to hand back

**A single self-contained `index.html`** (inline `<style>` + `<script>`; see §9
constraints) that:
1. Renders **Screen A** and **Screen B** (a toggle/hash is fine).
2. Has **representative static placeholder data in every §4 slot** and shows the
   key §5 states (either multiple mocks or lightweight JS toggles). I want to see
   the design *fully populated and dense*, not empty scaffolding.
3. Uses **clean, semantic, stable hooks** — meaningful `id`s / `class`es /
   `data-*` on every dynamic slot (the transcript container, each pane body, the
   PAD bars, a metric-row template, the connection dot, the tab badges, etc.).
   This is how I wire real data in — treat the DOM structure as an API.
4. Imports/inlines the Australis tokens; no invented palette.

I will then **swap your placeholder content for live `fetch()` + `EventSource`
calls** against the real endpoints (§9). The cleaner and more component-shaped
your DOM, the faster and safer that wiring is. A short note listing your mount
points / how you'd expect data injected is very welcome.

---

## 9. Hard technical constraints (these make it wire-able)

- **Single file. No build step. No CDN. No external network at runtime.** This
  ships to an internal LAN and must work offline. That means: **no Google Fonts /
  no web-font CDN** (use a system monospace stack), no CDN JS/CSS libraries,
  everything inline. (Icons: use unicode glyphs `➜ ✓ ✗ ! ● ✦ ❯` or hand-inlined
  SVG — Australis uses Lucide-style 1.75-stroke line icons; inline them.)
- **Vanilla HTML/CSS/JS.** No framework (the production app is framework-free
  vanilla JS). React/Vue prototypes can't be wired in.
- **All dynamic text is escaped** on the real side (untrusted upstream content);
  assistant/reasoning bodies go through a safe-Markdown renderer (escape-first,
  whitelist subset). Don't design anything that depends on raw HTML injection.
- **The real data contracts** (so your structure maps to the wire — you don't
  implement these, just leave homes for their outputs):
  - `GET /api/agents` → agent list (for the setup picker).
  - `POST /api/sessions {agent_id, bifrost_plane?}` → `{session_id, agent_id, bifrost?}`.
  - `GET /api/sessions/{id}/messages` → `{items:[{seq, role, content}], …}` (the transcript on open, incl. the seeded first-message).
  - `POST /api/turns/{id} {content}` → `{turn_id}`, then **`GET /api/turns/{id}/stream` (SSE)** — event vocab: `text`, `thinking`, `tool_start`, `tool_result`, `done`, `error`, `awaiting_llm_first_token`, terminal events. `POST /api/turns/{id}/cancel`.
  - `GET /api/sessions/{id}/tools` → tool inventory. `GET /api/sessions/{id}/bifrost` → binding state.
  - `GET /api/affect/{agent_id}` / `GET /api/agents/{id}/persona_state` → PAD + relations + dominant_emotion (the persona pane + strip).
  - **`GET /api/admin/events` (SSE)** → the admin lifecycle log.

---

## 10. Tone check

The user is an engineer who respects the tool that respects *their* attention.
The winning design is **quietly excellent**: dense but never cramped, alive but
never busy, cool and legible, with the aurora as a single confident signature.
Impress by making six live data streams feel *calm and readable at a glance* —
that's the hard, valuable thing here, not decoration.
