memory: snapshot — queue web-UI iteration-3 (design re-import) + memory viewer + markdown pass-2 for fresh context

This commit is contained in:
vh
2026-07-07 01:28:04 -07:00
parent c988f273b1
commit 24644ab90e
+14 -2
View File
@@ -1,6 +1,6 @@
# Persistent memory — ratatoskr
_Last updated: 2026-07-06_
_Last updated: 2026-07-07_
This file captures durable intent and supporting evidence (goals, decisions,
foot-gun warnings, in-flight state) across context resets. Read it at session
@@ -39,7 +39,18 @@ upstream API key stays server-side (INV-003).
## Current state / in-flight
_As of 2026-07-06 (session cont.):_
_As of 2026-07-07 (session cont.):_
**⏭ QUEUED FOR FRESH-CONTEXT IMPLEMENTATION (operator: "/snapshot and implement that and memory viewer on fresh context").** Three work items, all pre-scoped:
**(A) Design prototype iteration-3 — re-pull + adapt** (`DesignSync get_file` projectId `bc0b65d1-a33e-422a-8bc1-3635c9112775`, file `Ratatoskr Console.dc.html`; design scopes already granted — no /design-login). RE-PULL for exact coords; three changes vs the shipped v0.20.4:
1. **Sparkline background** — the relation-row 56×13 spark SVG gets a bg `<rect x=0.5 y=0.5 width=55 height=12 fill="url(#sparkGrid)" stroke=var(--border-subtle) stroke-width=0.5 stroke-opacity=0.6>` BEHIND the polyline. New def: `<pattern id="sparkGrid" width=10 height=6.5 patternUnits=userSpaceOnUse><path d="M 10 0 L 0 0 0 6.5" fill=none stroke=var(--border-subtle) stroke-width=0.5 stroke-opacity=0.6></pattern>` (subtle grid cell). Add pattern to the hidden `<defs>` + the rect to the metric-row spark (and consider the same bg on the PAD area).
2. **PAD strips → per-turn Δ bars ("read as vertical shifts")** — REPLACE the current SVG polyline strip (`stripPoints`) with a column of 12 HTML rows (newest at BOTTOM), each 8px tall holding a horizontal bar offset L/R from the center line (`left:12.5px`) by that turn's Δ: `<div style="left:{l}px;width:{w}px;height:{h}px;opacity:{o};background:<axis-color>;top:50%;transform:translateY(-50%);border-radius:2px">`. Container `data-hook=strip-{p,a,d}` 26×132 `position:relative` with a center line + an inset flex column `justify-content:space-between padding:4px 0`. Eyebrow → "Δ/turn · last 12 · newest ↓". Compute `stripP/A/D` = arrays of `{l,w,h,o,t}` from per-turn deltas of AFFECT_HIST.pad[axis] (delta sign → left/right of center; magnitude → width; age → opacity fade).
3. **Mood orbit → DIMETRIC OPEN BOX + JS-animated replay** — REPLACE the v0.20.4 isometric cube. New frame: viewBox **124×140**; "dimetric open box · **azimuth 35° elevation 25° · D→right, A→left-back, P→up**" (NEW projection — different axes from the current `proj3`). Two faces: a **ghost WALL** (A×P plane at d=−1, `fill=var(--aus-green) op=0.05`, grid lines, P-axis = the wall's rear edge, carries the **P readout**) + a **FLOOR** (D×A plane, positive halves shaded `--aus-cyan op=0.07` + `--aus-blue op=0.07`, grid lines). Axis labels colored: **+D cyan** (112,100) · **+A blue** (14,108) · **+P green** (54,10.5). The dynamic part is a template hole `{{ orbitDynamics }}` commented "**animated trajectory + shadow + P readout (JS-DRIVEN replay)**" → implement in JS: derive the dimetric projection (az35/el25, D-right/A-left-back/P-up), plot the PAD-history trail + a floor-shadow + the P readout on the wall, ANIMATED as a replay over time (no SMIL/CSS-keyframes in the prototype — it's explicitly JS-driven). RE-PULL the static frame polygon/line coords (they're in the prototype; too many to bank here). Existing `sparkFade`/`stripFade{P,A,D}` gradient defs unchanged.
**(B) Memory viewer (step ②, operator picked the CONSOLE PANE).** New debug read route on the combined provider `GET /memory/chunks?agent_id=&end_user_id=` (reads `memory.db`; MIRRORS the #18-D2 `GET /affect/state/{agent_id}` provider-read pattern — bifrost's memory protocol has NO list-all verb, so this is explicitly OUR debug read on OUR store per [[feedback_debug_surface_uses_canonical_surface_only]]) → web proxy `GET /api/memory/chunks` (server-supplied end_user, like `/api/affect`) → a live-polling "MEMORY" pane in the right console showing content·scope·origin per chunk. **Bundle a controlled bound 6-turn session** (+ a salient fact, via `--bifrost-url http://10.100.10.50:8392`) to PROVE the round-trip + settle why memory stayed 0/0 (memory-watch timed out 13min at 0 chunks / 0 idempotency → suspect the operator's session bind wasn't memory-granted OR closed pre-promotion; the viewer makes bind+promotion state visible). Contract-worthy (amend `web_debug_surface.contract.md`, mirror the D2 provider-read + proxy + pane shape).
**(C) Markdown pass-2** — tables, nested lists, ordered-list numbering, streaming robustness (pass-1 RP speech/action coloring + paragraph reflow shipped `v0.20.6`).
**SHIPPED — web UI redesign via Claude Design (`v0.20.0`, MINOR, operator-approved).** The Claude Design prototype **`Ratatoskr Console.dc.html`** (project `bc0b65d1-a33e-422a-8bc1-3635c9112775`) was pulled via `DesignSync get_file` (design scopes already granted this session — no `/design-login` needed) and adapted into `src/ratatoskr/web/static/index.html`: translated OUT of the `.dc.html` dialect (`<x-dc>`/`<sc-if>`/`<sc-for>`/`{{}}`/`DCLogic`/external `_ds/` CSS — none runnable) into single-file/no-CDN/vanilla, with ALL real `/api/*` fetch + SSE wired into its DOM (endpoint set + SSE vocab unchanged from the prior SPA — ported verbatim, only DOM hooks re-targeted). New shape = a **3-column command-console**: left engine-ticker rail (DEBUG+ADMIN+tool/turn-lifecycle MERGED into one timeline via `tickerAdd` + a tools-armed chip list + a FULL-detail Bifrost rail pane) · center conversation (per-turn INLINE chain-of-thought, replacing the Think pane) · right RESIZABLE affect console (dominant/canonical-mood centerpiece + bipolar PAD faders EACH with a turn-to-turn Δ+sparkline + a P×A mood orbit + relations metric rows + canonical directive). ADDED (round 2, operator-requested): a **light/dark theme toggle** (dark default; FULL token override — surfaces+fg+borders+accent-as-text, since the designer's light theme only did surfaces → would've been light-on-light) + a **full-detail Bifrost pane** (endpoint/connected/consumer/caps/tools) + fixed the **engine-ticker spine** (was a container-anchored `::before` that scrolled out of view on auto-scroll → re-anchored to a content-height `.ticker-inner` wrapper) + **per-fader PAD turn-to-turn Δ+sparkline** (fills the room beside each meter, from the deduped-per-turn AFFECT_HIST) + an **INLINED data-URI favicon** (operator's `/home/lkraven/rata.png` — chibi aurora squirrel — downscaled 1024→64px via PIL, ~8.6KB base64, kills the /favicon.ico 404). ALL server routes UNCHANGED (**84 web tests green**). Verified BOTH lenses: `pytest tests/test_web_*` (84) + node Playwright drove the real UI end-to-end against personal :8081 (session open → Sindra seeded greeting → live turn SSE → affect console + relations + bifrost detail; theme toggle + PAD deltas + ticker spine + no-favicon-404 all confirmed, dark+light screenshots). `:8765` restarted on the new code. Contract `web_debug_surface.contract.md` amended in-commit (v0.20.0 presenter renames: `renderBifrostState`→`renderBifrost`, `renderAffectPane`→`renderConsole`, `setPersonaStrip` removed; INV-001/INV-004 held). **HONEST-SHAPE call (INV-001, agent-discretion within settled policy):** the dominant-emotion centerpiece shows a real OCC emotion (Tier-1) OR the CANONICAL mood word (Tier-3 e.g. Sindra→"positive and energized", dimmed) OR "—", NEVER a fabricated emotion; the affect-derived grid drops non-emitted intensity/decay-τ, shows only real/client-derived cells. **OPEN (operator's call):** the per-fader PAD Δ placement is a sensible default — operator offered to have the designer spec the exact treatment (hooks are in place to swap it). **`v0.20.1` patch (operator-reported UI):** fixed the relations sparkline overflowing onto the `n` (evidence-count) column — the sparkline grows one char/sample (HIST_CAP=24) and overflowed its fixed grid cell, covering `n`; now capped (relations last-8, faders last-7) + `overflow:hidden` clip; verified via Playwright injecting a 24-sample history (sparkline→n bounding-box overlap = 0). ADDED native `title` mouseover hints on all 3 PAD faders + every relationship metric row (meaning + range; static METRIC_HINTS, esc()'d). Added `state.lastSnap` (console can re-render without a refetch). Playwright-verified.
@@ -169,6 +180,7 @@ decision. Captures rationale that won't be obvious from code alone.
- `[2026-07-06]` **Web UI: pivot from incremental CSS polish to a designed prototype (Claude Design) that I wire into.** Operator saw an Australis polish pass ("looks fine, but we're attacking it differently") and chose the prototype route — a designer builds the visual shell, I wire real data/SSE into its DOM. Authored the full design brief `docs/design/ratatoskr-web-design-brief.md` (complete information inventory of every pane/datum/state + Australis direction + single-file/no-CDN/vanilla wire-ability constraints). **Tracking surface:** the brief file + Claude Design project `bc0b65d1-a33e-422a-8bc1-3635c9112775` (file `Ratatoskr Console.dc.html`). Import mechanism = the `DesignSync` MCP; blocked on `/design-login` (claude.ai design scopes) — see Current state for the post-auth wiring plan.
- `[2026-07-07]` **Affect-egress reference delivered by worldtree-dev + a we-framing render DRIFT-WATCH banked.** worldtree-dev shipped `docs/affect-egress-consumer-reference.md` (`74d2408`, their origin/main) — the authoritative DELIVERED-on-wire vs HIDDEN (system-prompt-only) map for our affect surface. Confirms the v0.20.x console consumes it correctly: DELIVERED via affect.emit = pad + relations[RelationEdge] + dominant_emotion (**type-only, b23**; the #204 `affect_update` SSE is SUPPRESSED for Tier-3, so its richer `emotions_active` is Tier-1-only — we don't get it, and correctly poll our own affect store post-turn instead). HIDDEN render OUTPUTS are deterministically reconstructable from the canon; we reconstruct only the two FULLY-reconstructable (mood descriptor via `canonMood`, relationship directive via `canonDirective`) and SKIP the PARTIAL mood-directive (dominant_emotion is type-only/no-intensity → can't tell if the OCC directive fires at salience≥0.2 vs the PAD-band fallback) — honest per INV-001. Vendoring the ref doc as a `tolerate_drift` pin is SURFACED to Vuong (worldtree-dev will co-sign + honor a ping-on-change handshake, same as the d2-canon). **WE-FRAMING DRIFT-WATCH → STOOD DOWN (worldtree-dev 2026-07-07, `01KWXMQPHN…`).** The b24 3-gate we-framing conditional (drop "; avoid premature we-framing" under unsafe_capable+deep-warmth+expressive) was **REVERTED** — Vuong reframed it. So **`canonDirective` STAYS UNCONDITIONAL** (always appends the clause), which is CORRECT: it matches the currently-deployed renderer (b23) AND my pinned `affect-egress-consumer-reference.md` §2d (the doc reverted too — nothing changed on the wire or in my pin; NO re-vendor needed). The HOLD was right → ZERO rework. **NEW forward-watch (replaces this one):** the we-framing gate was a SYMPTOM — the render bakes enterprise safety-guards into the directive strings, so even `full`-tier characters get DEFANGED emotions (a hostile villain told to "keep a firm emotional boundary"). Fix = a **use-case-segregated persona render** (assistant / companion / RP-gaming), now a fresh **brokkr deep-research epic**. When it lands + is implemented, the render behavior for character/RP agents (→ our `canonDirective` + `canonEmotionDirective` reconstruction + the vendored d2 canons) will change MATERIALLY — worldtree-dev re-engages ratatoskr-dev then with the new reconstruction spec + a coordinated re-vendor. Until then: NO action, reconstruction stays as-is. [my unsafe_capable/mood_tier heuristic — character→full, agent→safe — was confirmed correct + is banked for whenever tier-gating returns]
- `[2026-07-07]` **Web-UI next-work QUEUED for a fresh-context session (operator-directed `/snapshot` handoff) — full specs in Current state § ⏭ QUEUED.** Three deferred-but-scoped items: **(A)** Claude Design prototype ITERATION-3 re-import (sparkline bg grid `<pattern>`, PAD strips → per-turn-Δ-bar HTML columns, mood orbit → DIMETRIC open-box az35/el25 D-right/A-left-back/P-up + JS-animated replay `orbitDynamics`); **(B)** memory viewer console pane (provider `GET /memory/chunks` read → web proxy → polling pane, mirror #18-D2; bundle a 6-turn bound round-trip proof to settle the 0/0-memory mystery); **(C)** markdown pass-2 (tables / nested lists / streaming). **Tracking surface:** the Claude Design projectId `bc0b65d1-a33e-422a-8bc1-3635c9112775` (durable — re-pull for exact coords) + this snapshot capture; operator-directed. Design scopes already granted (no `/design-login`).
- `[2026-07-07]` **Markdown pass-1 SHIPPED (`v0.20.6`) — RP semantic coloring + paragraph reflow (operator-directed markdown rework, step ①).** The transcript renderer (`markdownSafe`/`mdInline`) now colors the two roleplay registers: `"quoted"` dialogue → SPEECH (bright `--md-speech`=fg-0), `*asterisk*` → ACTION/narration (muted-italic `--md-action`=fg-3, on `em.md-action`); both tunable via 2 CSS vars that cascade through `--fg-*` so they auto-adapt to the light theme. Plain text stays default narration. **KEY ORDERING:** speech-wrap runs BEFORE the em/link passes so a generated `class="md-action"` / `href="…"` quote can't be mis-read as dialogue (adversarially verified). Straight + smart quotes; apostrophes don't trigger; unbalanced/half-streamed quotes stay uncolored until they close. ALSO fixed the ugliest existing bug: single newlines were hard-`<br>`s → now CommonMark soft-breaks (space); a hard break needs 2+ trailing spaces or a trailing `\`. INV-004 escape-first preserved (html inside a quote escaped). Verified: 10-case Playwright unit-check of `markdownSafe` (speech/action/attr-trap/apostrophes/mixed/reflow/hard-break/escaping/unbalanced/paragraphs) all green + a visual render. Patch bump. **Markdown rework remaining: pass-2 (tables / nested lists / ordered-list numbering / streaming robustness); + the MEMORY VIEWER (step ②, console pane recommended) still queued.**
- `[2026-07-07]` **Affect-derived tooltips (`v0.20.5`) + transparent squirrel vendored + v0.20.0–.5 PUSHED to origin (operator-authorized).** Native `title` hints on all 6 affect-derived cells (samples/updated/baseline P·A/drift Δv/volatility — each with meaning + Tier-1-vs-Tier-3 availability). Committed the transparent full-res brand mark at `docs/design/ratatoskr-mark.png` (1024², alpha; the bg-removed source the inlined favicon derives from — reproducible via the documented ImageMagick corner floodfill). The web-UI redesign arc (v0.20.0 Claude Design console → .1 sparkline-overflow+tooltips → .2 context-injection → .3 squirrel brand/favicon → .4 SVG sparklines+3D cube → .5 derived tooltips) is now all on `origin/main`.
- `[2026-07-07]` **SVG sparklines + 3D mood cube imported from the updated Claude Design prototype (`v0.20.4`) — operator: "the svg sparklines and the new 3d graph".** Re-pulled `Ratatoskr Console.dc.html` via `DesignSync get_file` (designer iterated the same project, +6KB). Adapted 3 SVG systems out of the `.dc.html` into vanilla, replacing the unicode-char sparklines: **(1)** per-PAD-fader VERTICAL strips (`stripPoints`, 26×132 SVG beside each bar — time down Y newest-at-bottom, value on X ±11, `stripFade{P,A,D}` gradient, dot at newest; this also nails the earlier "next to each meter" ask); **(2)** relation-row HORIZONTAL sparklines (`sparkPointsH`, 56×13, auto-scaled, `sparkFade` gradient + end dot — also kills the old unicode-overflow "n behind graph" for good since it's a fixed-width SVG); **(3)** the mood-orbit reworked from a 2D P×A scatter into a **3D ISOMETRIC P×A×D cube** (`proj3`: P right-down/A left-down/D up, 2:1 iso, center 62,66, scale 26 — REVERSE-DERIVED from the design's placeholder now-point + verified: `x=62+26P−26A, y=66+13P+13A−26D`), with the trajectory + pulsing now-marker + a drop line to the D=−1 floor + a floor-shadow ellipse for depth. Gradients in one hidden `<defs>` svg. Removed the orphaned `sparkline()`/`_SPARK`. Contract amended. Playwright-verified (injected 24-sample history: 3 strips + 4 relation sparklines + the 3D cube trail/drop/floor all render; gradients resolve). Patch bump.