Files
ratatoskr/persistent-memory.md
vh 6e2822cfcb memory: snapshot — dots-tts + config-voices/two-voice split shipped; WT #401 personal-WT deadlock routed
Captures this session's durable state: the RP-voice rebuild (chatterbox->dots
v0.22.2, config-driven voices + two-voice dialogue/narration split v0.22.3) and
the personal WT :8081 deadlock recovery + root-cause routing to worldtree-dev
(WT #401). New substrate foot-guns: dots :8198 is a fleet switchboard, dots'
language validator is an alias-mapper, per-origin TTS toggle, WT hang signature,
dots-streaming-pcm-not-headerless. Three detail files added under
persistent-memory.d/.
2026-08-13 22:59:28 -07:00

285 lines
53 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Persistent memory — ratatoskr
_Last updated: 2026-08-13_
> **Always check for `/tmp/ratatoskr-dev-handoff.md`** — if it exists and its
> `Written:` stamp is under an hour old, read it (it carries the in-flight
> handoff from the previous session), then delete it. Older than an hour:
> stale — delete it unread.
This file captures durable intent and supporting evidence (goals, decisions,
foot-gun warnings, in-flight state) across context resets. Read it at session
start; treat it as one input alongside `CLAUDE.md` and the auto-memory system,
not as the single source of truth.
When durable state shifts enough to warrant capture, run `/snapshot` and
commit alongside the next commit per the persistent-memory commit-along rule
in `CLAUDE.md`.
---
## Repo purpose
Ratatoskr is a **dev-grade debug-observability TUI** for Worldtree's
Conversation API. 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:
agent SSE stream, persona/Vili affect dispatch, tool calls, Bifrost
handshake state, admin lifecycle events, optional raw server log.
Named after the squirrel that runs up and down Yggdrasil carrying messages
between layers. On-the-nose Worldtree resonance (Yggdrasil = the World Tree).
**Second identity (since 2026-06-14): the v1 Bifrost Tier-3 consumer/provider**
the durable persistence Worldtree writes Tier-3 agent affect (PAD/persona, `:8390`)
+ memory (`:8391`) into. Lives in `src/ratatoskr/provider/`, depends on `bifrost`
(`provider` optional-extra), separate from the conversation-API spec pin. So
ratatoskr now owns BOTH ends of the Bifrost round-trip — the lens #17 exploits.
**v0.15.0+ sibling browser surface** (`ratatoskr.web`, `ratatoskr-web` console
script): same five-pane debug surface over the same SSE wire, LAN-viewable.
Internal-LAN trust model — `0.0.0.0`, no auth/TLS/CORS (operator direction).
Disciplined regardless: transcript HTML-escapes assistant content (INV-004);
upstream API key stays server-side (INV-003).
## Current state / in-flight
_As of 2026-08-13:_
**Nothing in flight on ratatoskr's side. The RP-voice stack was rebuilt this session (chatterbox→dots, then config-driven voices + a two-voice dialogue/narration split) — all shipped + PUSHED (HEAD `5c3d0ad`, origin synced, tags `v0.22.2`/`v0.22.3`). The one open tail is upstream: WT #401 (worldtree-dev owns the personal-WT deadlock root-cause).** Details in Recent decisions; durable substrate below.
- **TTS = dots-tts + config-driven voices + two-voice split** — live on `ratatoskr-web` **pid 2290701** (`:8765`, dots + `voices.json` loaded). Backend is **dots-tts** via the fleet **switchboard** `http://10.100.79.3:8198/v1/audio/speech` (OpenAI-shaped `{input,voice,response_format,stream}`, 48kHz mono s16le, streaming placeholder-header WAV). `tts.py` is the single swap seam (`RATATOSKR_TTS_URL` overrides), NO affect. Per-agent voices live in **`~/.config/ratatoskr/voices.json`** (donut→donut single; sindra→miranda dialogue + emmie narration); an agent with a `narration_voice` gets the quote-split two-voice stitch (`tts_stream_stitched`, `src/ratatoskr/voices.py`).
- **Personal WT :8081 recovered + root-cause routed to WT #401** — it deadlocked after ~4 days (event-loop wedge from a background `context_promotion` sqlite error); infra-ops `docker restart`'d it, worldtree-dev owns the diagnosis. Ratatoskr auto-recovered (degrade path held; no ratatoskr restart). Only possible follow-up = a consumer-side repro if worldtree-dev asks.
**Deferred / queued (non-urgent, pre-existing — tracked, NOT this-session):** heid gates on the two-voice feature SKIPPED in-session (offered, not run — optional cross-frontier gate if wanted); TUI rip (`tui.py`+`tests/test_tui.py` delete cleanly, but `cli.py` is SHARED — relocate `USER_AGENT`/`ParsedArgs`/`_format_*` first; breaking public-surface removal → minor bump, operator approval); #368 backfill live-verify (synthetic legacy corpus); SDK **#371** (Rata = seed donor + future consumer; next = WT codegen spike; divergences D-1 unknown-SSE-skip / D-2 open-world-enums / D-3 typed-410); P06 referential-frame A/B/C probe (waits WT b122); R39 Phase-2 matched-quartets (confirmatory); bifrost snapshot-cursor adoption (normative, non-blocking).
**Live substrate / foot-guns:** branch `main`, HEAD `5c3d0ad` PUSHED; origin `git@gitea.phasefinal.com:vh/ratatoskr.git`; version **v0.22.3**. Deps: **`worldtree-sdk==1.2.0`**, **`bifrost==1.1.5`**/wire v0.7, WT openapi vendored 2.3.0, conversation-api-spec v1.1. **`uv sync --all-extras`** — dev deps are a `[project.optional-dependencies]` EXTRA; plain `uv sync` PRUNES pytest/respx. Personal WT on **b185** (`http://10.250.50.152:8081`) — **FOOT-GUN: it can deadlock into a live-socket/dead-worker hang (WT #401); symptom = TCP port open but ALL routes return 000 ("server disconnected without response"); fix = infra-ops `docker restart`, ratatoskr auto-recovers.** Surfaces: combined **`:8392`** provider (memory+affect) + **`:8765`** web (pid 2290701) — detached bare processes, no supervisor → re-stale on reboot (relaunch `source env.sh && setsid .venv/bin/ratatoskr-web --host 0.0.0.0 --port 8765`); `env.sh` sets REQUIRED `RATATOSKR_MEMORY_EMBEDDING_DIM=1024`; keys mode-600 in `~/.config/ratatoskr/provider.env`. **dots-tts `:8198` is now a fleet SWITCHBOARD** (fronts dots on `:8202`; +3.3ms; engine swaps = instant `.env` flips; v4 engine adds an optional `language` field). **FOOT-GUN: dots' `language` validator is an alias-mapper NOT a gatekeeper** — word-junk ('klingon') maps to a tag + generates; only structurally-invalid tokens (empty/punctuation/overlong) 400 → validate ourselves if we ever send `language`. **FOOT-GUN: browser auto-TTS is opt-in (`localStorage['ratatoskr-tts']='1'`), PER-ORIGIN** — localhost vs LAN-IP have separate storage, so the toggle doesn't carry between them. **FOOT-GUN: check owner-scoped agents via `GET /agents/<owner>:<name>` with the OWNER key, NOT admin (admin → false 404).** SDK-adapter foot-guns (cumulative): SDK reads = open-world dicts → presenters degrade-not-crash at 3 guard levels; all transport failures → `ConnectFailed(status=0)`; `local_agents` index v1→v2 SILENTLY DROPS pre-cutover agents. `graphify-out/` runs dirty (never stage). v1 = full Worldtree I/O coverage (`docs/coverage-map.md`).
## Recent decisions
Chronological log of decisions with `[YYYY-MM-DD]` prefix. One line per
decision. Captures rationale that won't be obvious from code alone.
- `[2026-08-12]` **Personal WT :8081 deadlocked after ~4 days → routed to worldtree-dev as WT #401; ratatoskr degrade path held.** Live-socket/dead-worker event-loop wedge (background `context_promotion` sqlite "unable to open database file"); recovered by infra-ops `docker restart`; ratatoskr auto-recovered (12/12 502 → 8/8 200, no ratatoskr restart). → `persistent-memory.d/2026-08-12-wt-401-personal-deadlock.md`
- `[2026-08-12]` **Config-driven voices + two-voice dialogue/narration split SHIPPED (v0.22.3, `5c3d0ad`).** `~/.config/ratatoskr/voices.json` (per-agent voice + optional `narration_voice`); new `src/ratatoskr/voices.py`; `tts_stream_stitched` replaces `tts_stream`; contract DEC-11 + INV-TTS-5/6/7. → `persistent-memory.d/2026-08-12-config-voices-two-voice.md`
- `[2026-08-12]` **dots-tts `:8198` became a fleet SWITCHBOARD (fronts dots `:8202`, +3.3ms); engine swaps are now instant `.env` flips.** v4 engine adds an optional `language` field; byte-compatible, no ratatoskr change. FOOT-GUN: dots' `language` validator is an alias-mapper not a gatekeeper (word-junk generates, doesn't 400) — validate ourselves if we ever send it.
- `[2026-08-11]` **Sindra voiced with the dots `miranda` voice (`3e69bc9`, no bump).** Ratatoskr-side per-agent voice map (resolved at `/api/tts` by `agent_id`); superseded next day by the config-driven map (DEC-11).
- `[2026-08-11]` **TTS migrated chatterbox-fast→dots-tts (v0.22.2, `38b78d8`), operator-directed after an A/B win.** OpenAI-shaped `/v1/audio/speech`, SR 24000→48000, default voice glados_25s→glados, serialized single-consumer; affect stays dropped; chatterbox `:8197` reclaimed. → `persistent-memory.d/2026-08-11-tts-dots-migration.md`
- `[2026-08-08]` **Crown-recall RESOLVED at b185 — identity-anchor rerank enrichment closed the class (gate: 79%→12% stress miss).** worldtree-dev shipped a rerank-input identity anchor (from character/terms metadata) + chain-wide tie-determinism (`50ecec7`) instead of the floor lever; `lexical_recall_gate --anchor crown --runs=8` at b185 = 12% miss / 0% knife-edge / item @rank 0 (vs 79% post-fold b184). Floor packet does NOT reopen; 12% residual = bare-query formulation ceiling. Arc complete our side; efficacy delta on WT #400.
- `[2026-08-07]` **Crown-recall traced to a general RETRIEVAL-CLASS limitation (exact-lexical match on an indexed surface form buried by dense-semantic neighbors), NOT persona/extraction/synonymy.** worldtree-dev decomposition (WT #400): no-stemming tokenizer + RRF top-10 knife-edge + reranker ownership-demotion. Operator-greenlit evidence-gated sequence (ship stemming fold → gate measures residual → hold `rerank_hybrid_floor` lever). Shipped `docs/diagnostics/lexical_recall_gate.py` (class acceptance instrument); pre-fold baseline control 0% / stress[crown] 100% miss. Awaiting worldtree-dev fold+#397 deploy ping for the pre/post delta. Thread `01KZETD98T`; siblings WT #399 (filed), #397 (committed, not deployed).
- `[2026-08-07]` **TTS migrated Zonos→chatterbox-fast (`:8197` bespoke schema); affect DROPPED (Turbo has no emotion knob, operator "drop it for chatterbox"), client-chunking DROPPED (no per-synth cap), language pin DROPPED, browser SR 44100→24000.** Pushed `19b499a`. English "German drift" real cause (after 2 wrong hypotheses) = Turbo model OVER-RUNS its generation TAIL on long single generations (garble in final ~2-3s, ZCR 1.58x); **fixed SERVER-SIDE by infra-ops (`max_chunk_chars=250`, image :v2, operator ear-confirmed).** Consumer: **REVERTED my interim `top_k/top_p/temp` curbs** (they made it WORSE — pulled garble onset earlier), send full text + default sampling; KEPT the `/api/tts` empty-200→503 guard as hygiene. Contract `donut_voiced_interview.contract.md` amended. Loop closed.
- `[2026-08-07]` **order_by=chapter tool flag → FILED as Worldtree #397 (DEFERRED to next session's contract pass).** Narrative/temporal-query gap ("first encounter in the dungeon"): `reference_knowledge` sorts by relevance not chronology; `provenance.chapter` is on every chunk but the consumer can't reorder native results (kb_bridge retired). Operator ruled the upstream sort flag the clean fix; worldtree-dev accepted, our fixture is the measurement instrument. Tracked at **Worldtree #397** (+ althing thread `01KZED2T3XHJ2WMS5NCYK42W6R`).
- `[2026-08-07]` **#393 (descriptive-query subject binding) CLOSED — persona-expand lever the win (4/10→9/10), tool directive the fleet floor.** `docs/diagnostics/descriptive_query_binding.py` is the canonical #393 fixture; two-mechanism split (cross-wing dilution vs fiction-scope selection). Commits `6c83a3b`/`4f4b5ad`/`2cc670e`.
- `[2026-08-07]` **Donut expand-don't-distill persona lever (`2cc670e`)** — keep full descriptive phrase + enrich toward entity vocab, never distill to bare keywords; measured 4/10→9/10 roid-rage binds persona-alone. Composes with near-miss LEAD (`37b67a5`).
- `[2026-08-07]` **TTS "unavailable" = stale web-server process** (predated POST /api/tts → 405); restarted + verified 200+WAV. Durability gap: bare nohup, no supervisor → systemd unit offered, deferred (operator's call).
- `[2026-08-03]` **fiction_wing_probe harness fix (`2111b1e`)** — fresh-session-per-query (WT #391 workaround) + NFKC/quote-fold on_target; surfaced+closed WT #391.
- `[2026-06-19]` **#18 D2 SHIPPED (`v0.17.14`, `39eebd1`) and the full #17+#18 arc PUSHED to origin** → `persistent-memory.d/2026-06-19-18-d2-shipped-v0-17-14-39eebd1-and-the-full-1.md`
- `[2026-06-19]` **bifrost repinned 0.8.0→0.10.0; `affect.fetch` became MANDATORY (strong-or-absent)**`persistent-memory.d/2026-06-19-bifrost-repinned-0-8-0-0-10-0-affect-fetch-be.md`
- `[2026-06-19]` **#18 D1 SHIPPED — composite `build_combined_app` on `:8392` (`v0.17.16`, `7f4ceaa`); #18 CLOSED; published `v0.18.0` (`359dbb1`)** → `persistent-memory.d/2026-06-19-18-d1-shipped-composite-buildcombinedapp-on-8.md`
- `[2026-06-19]` **op-feed handshake field-name fix (#17, `v0.17.17` `d60b77d`): `capabilities_requested`→`capabilities`**`persistent-memory.d/2026-06-19-op-feed-handshake-field-name-fix-17-v0-17-17.md`
- `[2026-06-19]` **Ratatoskr is a REFERENCE implementation of the Worldtree/Bifrost standard (operator)**`persistent-memory.d/2026-06-19-ratatoskr-is-a-reference-implementation-of-th.md`
- `[2026-06-19]` **Ratatoskr v1 is DERIVED from Worldtree I/O coverage (operator) — no self-defined feature ROADMAP**`persistent-memory.d/2026-06-19-ratatoskr-v1-is-derived-from-worldtree-i-o-co.md`
- `[2026-06-20]` **#18's final leg PROVEN — composite `:8392` WT-driven smoke ran end-to-end + persisted** → `persistent-memory.d/2026-06-20-18-s-final-leg-proven-composite-8392-wt-drive.md`
- `[2026-06-20]` **#17 CLOSED in the tracker.** Shipped end-to-end (`v0.17.8``.13` + op-feed field fix `v0.17.17`); the 2026-06-20 composite smoke re-exercised its op-feed live. Closing comment captures the full both-plane proof. Open issues now just #11 (scope-blocked) + #10 (watch).
- `[2026-06-20]` **Sindra has real PAD but ~empty memory — the affect/memory persistence asymmetry, confirmed on real sessions**`persistent-memory.d/2026-06-20-sindra-has-real-pad-but-empty-memory-the-affe.md`
- `[2026-06-29]` **Web SPA combined-bind default (`v0.18.1`, `719e4d6`) — operator-caught gap**`persistent-memory.d/2026-06-29-web-spa-combined-bind-default-v0-18-1-719e4d6.md`
- `[2026-06-29]` **bifrost repinned 1.0.0 (`v0.18.2`, `af67ad9`)**`persistent-memory.d/2026-06-29-bifrost-repinned-1-0-0-v0-18-2-af67ad9.md`
- `[2026-06-30]` **Worldtree v1.0.0b1→b2 consumer adaptation: eager turn-launch statuses (`v0.18.3` `b2e4901`, `v0.18.4` `e4317f6`)**`persistent-memory.d/2026-06-30-worldtree-v1-0-0b1-b2-consumer-adaptation-eag.md`
- `[2026-06-30]` **Verify-against-the-real-spec-before-committing caught a real upstream gap**`persistent-memory.d/2026-06-30-verify-against-the-real-spec-before-committin.md`
- `[2026-06-30]` **regard is a DEAD AXIS in Worldtree's emitted affect (caught provider-side; worldtree-dev confirmed + escalated to Vuong)**`persistent-memory.d/2026-06-30-regard-is-a-dead-axis-in-worldtree-s-emitted.md`
- `[2026-06-30]` **v1 coverage-audit kicked off; coverage ledger written (`docs/coverage-map.md`) — the first one**`persistent-memory.d/2026-06-30-v1-coverage-audit-kicked-off-coverage-ledger.md`
- `[2026-06-30]` **Scope mandate A locked (operator): v1 "done" = every frozen I/O point CLASSIFIED (covered-or-excluded-with-rationale), zero unaccounted — NOT a feature-complete client**`persistent-memory.d/2026-06-30-scope-mandate-a-locked-operator-v1-done-every.md`
- `[2026-06-30]` **Finding P-1 (pin drift) + pin-remediation PENDING**`persistent-memory.d/2026-06-30-finding-p-1-pin-drift-pin-remediation-pending.md`
- `[2026-06-30]` **(b) Tier-1 frontier SCOPED, ready for a contract-first TDD cycle (next focused work)** → `persistent-memory.d/2026-06-30-b-tier-1-frontier-scoped-ready-for-a-contract.md`
- `[2026-06-30]` **(b1) SSE-resume SHIPPED (`v0.18.5`) — `stream_turn_resilient` (sse_client.py)** → `persistent-memory.d/2026-06-30-b1-sse-resume-shipped-v0-18-5-streamturnresil.md`
- `[2026-06-30]` **(b2) session-picker SHIPPED (`v0.18.7`) — bare TUI mode → startup picker (design-brief §4)** → `persistent-memory.d/2026-06-30-b2-session-picker-shipped-v0-18-7-bare-tui-mo.md`
- `[2026-06-30]` **capabilities+me slice SHIPPED (`v0.18.8`) — `GET /me` + `GET /capabilities` consumed via a new `--whoami` one-shot**`persistent-memory.d/2026-06-30-capabilities-me-slice-shipped-v0-18-8-get-me.md`
- `[2026-07-01]` **b1 (SSE-resume) heid-code-review panel: ZERO findings — cross-model-verified clean**`persistent-memory.d/2026-07-01-b1-sse-resume-heid-code-review-panel-zero-fin.md`
- `[2026-07-01]` **`GET /sessions/{id}/tools` quick-win SHIPPED (`v0.18.9`) — owner-scoped tool inventory in the TUI Tools pane** → `persistent-memory.d/2026-07-01-get-sessions-id-tools-quick-win-shipped-v0-18.md`
- `[2026-07-01]` **BifrostState pane SHIPPED (`v0.18.10`) — `GET /admin/sessions/{id}/bifrost` in a new TUI "Bifrost" pane; the FIRST admin-key consumer in ratatoskr**`persistent-memory.d/2026-07-01-bifroststate-pane-shipped-v0-18-10-get-admin.md`
- `[2026-07-01]` **LEDGER CORRECTION: #11 (AdminEvents) is NO LONGER BLOCKED**`persistent-memory.d/2026-07-01-ledger-correction-11-adminevents-is-no-longer.md`
- `[2026-07-01]` **AdminEvents pane SHIPPED (`v0.18.11`) — `GET /admin/events` SSE in a new TUI pane; #11 closed-by-build; Tier 1 (debug-observability core) COMPLETE**`persistent-memory.d/2026-07-01-adminevents-pane-shipped-v0-18-11-get-admin-e.md`
- `[2026-07-01]` **Tier-2 SHIPPED (`v0.19.1`) — transient-characters CRUD + persona-state write; the v1 coverage-audit CONVERGES (zero in-scope gaps)**`persistent-memory.d/2026-07-01-tier-2-shipped-v0-19-1-transient-characters-c.md`
- `[2026-07-01]` **env.sh now PERSISTS the web Bifrost-bind vars (gitignored, local-only)**`persistent-memory.d/2026-07-01-env-sh-now-persists-the-web-bifrost-bind-vars.md`
- `[2026-07-01]` **Tier-3 stores RESET (operator-directed)**`persistent-memory.d/2026-07-01-tier-3-stores-reset-operator-directed.md`
- `[2026-07-01]` **Embedding-latency loop RESOLVED — it was WORLDTREE's, not ratatoskr (the consumer/provider thesis paid off again)**`persistent-memory.d/2026-07-01-embedding-latency-loop-resolved-it-was-worldt.md`
- `[2026-07-01]` **Web debug-surface parity SHIPPED (`v0.19.2`, `a0a9d5f`) — direct in-session TDD**`persistent-memory.d/2026-07-01-web-debug-surface-parity-shipped-v0-19-2-a0a9.md`
- `[2026-07-01]` **heid-code-review (`v0.19.3`, `75dec01`) — panel caught 2 real client-side SSE-lifecycle bugs TDD missed**`persistent-memory.d/2026-07-01-heid-code-review-v0-19-3-75dec01-panel-caught.md`
- `[2026-07-01]` **Affect snapshot shape CHANGED valence→relations (relation_edge/1) — the persona pane was reading a dead field**`persistent-memory.d/2026-07-01-affect-snapshot-shape-changed-valence-relatio.md`
- `[2026-07-01]` **Trust/warmth VALUES converge and go FLAT at confidence 1.0 — that's WAD, not a stuck pane**`persistent-memory.d/2026-07-01-trust-warmth-values-converge-and-go-flat-at-c.md`
- `[2026-07-01]` **relation_context "stranger" + agency-all-zero flagged to worldtree-dev → both WAD/intentional-v1-deferrals**`persistent-memory.d/2026-07-01-relationcontext-stranger-agency-all-zero-flag.md`
- `[2026-07-01]` **Persona pane displays the CANONICAL affect→NL Worldtree injects — ADOPT, don't invent (operator steer + reference-impl posture)**`persistent-memory.d/2026-07-01-persona-pane-displays-the-canonical-affect-nl.md`
- `[2026-07-01]` **Sindra PAD is over-regulated — characterized via controlled probe, flagged to worldtree-dev (separate affect slice)**`persistent-memory.d/2026-07-01-sindra-pad-is-over-regulated-characterized-vi.md`
- `[2026-07-01]` **Memory plane PROVEN healthy end-to-end**`persistent-memory.d/2026-07-01-memory-plane-proven-healthy-end-to-end.md`
- `[2026-07-01]` **Salience scorer non-discriminating → 3-way routing**`persistent-memory.d/2026-07-01-salience-scorer-non-discriminating-3-way-rout.md`
- `[2026-07-01]` **Canonical check BLOCKED an access_tally fork (reference-impl posture held)**`persistent-memory.d/2026-07-01-canonical-check-blocked-an-accesstally-fork-r.md`
- `[2026-07-01]` **relation_context coherence FIXED upstream (my flag → Worldtree Wave-0, IMPLEMENTED v1.0.0b5)**`persistent-memory.d/2026-07-01-relationcontext-coherence-fixed-upstream-my-f.md`
- `[2026-07-01]` **Foot-gun (measurement, self-caught before flagging): establish the baseline before claiming a rate**`persistent-memory.d/2026-07-01-foot-gun-measurement-self-caught-before-flagg.md`
- `[2026-07-02]` **Salience finding matured into brokkr R28 (OPEN) — ratatoskr is the eval instrument**`persistent-memory.d/2026-07-02-salience-finding-matured-into-brokkr-r28-open.md`
- `[2026-07-02]` **Relational-dynamics arc LIVE on demo (Worldtree v1.0.0b9) — driven by MY relation_context flag**`persistent-memory.d/2026-07-02-relational-dynamics-arc-live-on-demo-worldtre.md`
- `[2026-07-02]` **R28 (salience→promotion-worthiness) CLOSED (operator-directed)**`persistent-memory.d/2026-07-02-r28-salience-promotion-worthiness-closed-oper.md`
- `[2026-07-02]` **R29 (PAD mood-dynamics) finding SHIPPED as Worldtree's A1 anchor fix (demo v1.0.0b14, `e1cdf82`)**`persistent-memory.d/2026-07-02-r29-pad-mood-dynamics-finding-shipped-as-worl.md`
- `[2026-07-03]` **R30 Phase-1 φ0 measured — deployed engine CONFIG-FAITHFUL (φ0≈0.95)**`persistent-memory.d/2026-07-03-r30-phase-1-0-measured-deployed-engine-config.md`
- `[2026-07-03]` **R30 forward disposition (brokkr-owned; tracked at brokkr R30, "brokkr/worldtree will ping")**`persistent-memory.d/2026-07-03-r30-forward-disposition-brokkr-owned-tracked.md`
- `[2026-07-03]` **Relational-arc verify DEFERRED — `relations[]` is Bifrost-provider-only (ADR-0009), confirmed both ways**`persistent-memory.d/2026-07-03-relational-arc-verify-deferred-relations-is-b.md`
- `[2026-07-04]` **R30 CLOSED on offline-tests + human face-validity (operator steer, relayed via worldtree-dev)**`persistent-memory.d/2026-07-04-r30-closed-on-offline-tests-human-face-validi.md`
- `[2026-07-05]` **Authored-history-write primitive proposed -> accepted as Worldtree #347 (Worldtree owns the engine design; ratatoskr = reference consumer)**`persistent-memory.d/2026-07-05-authored-history-write-primitive-proposed-acc.md`
- `[2026-07-05]` **#347 v1 wire validated as reference consumer (GREEN)** → `persistent-memory.d/2026-07-05-347-v1-wire-validated-as-reference-consumer-g.md`
- `[2026-07-06]` **Sindra role character-rp -> character (operator)**`persistent-memory.d/2026-07-06-sindra-role-character-rp-character-operator.md`
- `[2026-07-06]` **Sindra persona/OCEAN DECLARED -> mood fixed (the full diagnostic converged on a stale personal container)**`persistent-memory.d/2026-07-06-sindra-persona-ocean-declared-mood-fixed-the.md`
- `[2026-07-06]` **OpenAPI re-vendored 2.2.0->2.3.0 (`75da676`, pin-only no bump)**`persistent-memory.d/2026-07-06-openapi-re-vendored-2-2-0-2-3-0-75da676-pin-o.md`
- `[2026-07-06]` **#347 authored-history-write CONSUMER SIDE SHIPPED (`v0.19.6`) — direct in-session TDD** → `persistent-memory.d/2026-07-06-347-authored-history-write-consumer-side-ship.md`
- `[2026-07-06]` **Tail-2 SHIPPED (`v0.19.7`) — Tier-3 prose docs re-vendored + persona_state body-shape aligned**`persistent-memory.d/2026-07-06-tail-2-shipped-v0-19-7-tier-3-prose-docs-re-v.md`
- `[2026-07-06]` **Sindra rewritten onto a #347 authored first-message + first-message-preset AUTO-SEED SHIPPED (`v0.19.8`)**`persistent-memory.d/2026-07-06-sindra-rewritten-onto-a-347-authored-first-me.md`
- `[2026-07-06]` **Web UI now RENDERS the seeded first-message (`v0.19.9`) — operator-reported "i don't see Sindra's greeting on the web ui"**`persistent-memory.d/2026-07-06-web-ui-now-renders-the-seeded-first-message-v.md`
- `[2026-07-06]` **Web UI: pivot from incremental CSS polish to a designed prototype (Claude Design) that I wire into**`persistent-memory.d/2026-07-06-web-ui-pivot-from-incremental-css-polish-to-a.md`
- `[2026-07-07]` **Affect-egress reference delivered by worldtree-dev + a we-framing render DRIFT-WATCH banked**`persistent-memory.d/2026-07-07-affect-egress-reference-delivered-by-worldtre.md`
- `[2026-07-12]` **R34/R35 character-self-report reframe LIVE (WT b53); affect-half VALIDATED in prod, powered memory-half eval GREENLIT + designed**`persistent-memory.d/2026-07-12-r34-r35-character-self-report-reframe-live-wt.md`
- `[2026-07-12]` **Capture-path resolved → a worldtree producer-probe (ratatoskr-caught blocker)**`persistent-memory.d/2026-07-12-capture-path-resolved-a-worldtree-producer-pr.md`
- `[2026-07-12]` **bifrost 1.1.1 adopted (v0.20.10, pushed) — the library-level fix for the frozen-v0.6 handshake leak**`persistent-memory.d/2026-07-12-bifrost-1-1-1-adopted-v0-20-10-pushed-the-lib.md`
- `[2026-07-10]` **Bifrost bound-handshake blocker → bifrost 1.1.0 broke frozen-v0.6; fixed by Worldtree b47/wire-v0.7, our side needed ZERO change**`persistent-memory.d/2026-07-10-bifrost-bound-handshake-blocker-bifrost-1-1-0.md`
- `[2026-07-09]` **Sindra PATCHed to `character-rp` → Deckard reasoning-RP seat (operator-directed, INTERIM)**`persistent-memory.d/2026-07-09-sindra-patched-to-character-rp-deckard-reason.md`
- `[2026-07-08]` **PAD display relaxed for R32-1B unbounded-z, done PROACTIVELY (`v0.20.9`, patch, operator-directed "sindra full and unbounded")**`persistent-memory.d/2026-07-08-pad-display-relaxed-for-r32-1b-unbounded-z-do.md`
- `[2026-07-07]` **Web-UI iteration-3 SHIPPED (`v0.20.7`, patch) — all three queued items + the memory 0/0 root-caused**`persistent-memory.d/2026-07-07-web-ui-iteration-3-shipped-v0-20-7-patch-all.md`
- `[2026-07-07]` **Web-UI next-work QUEUED for a fresh-context session (operator-directed `/snapshot` handoff) — full specs in Current state § ⏭ QUEUED**`persistent-memory.d/2026-07-07-web-ui-next-work-queued-for-a-fresh-context-s.md`
- `[2026-07-07]` **Markdown pass-1 SHIPPED (`v0.20.6`) — RP semantic coloring + paragraph reflow (operator-directed markdown rework, step ①)**`persistent-memory.d/2026-07-07-markdown-pass-1-shipped-v0-20-6-rp-semantic-c.md`
- `[2026-07-07]` **Affect-derived tooltips (`v0.20.5`) + transparent squirrel vendored + v0.20.0.5 PUSHED to origin (operator-authorized)**`persistent-memory.d/2026-07-07-affect-derived-tooltips-v0-20-5-transparent-s.md`
- `[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"**`persistent-memory.d/2026-07-07-svg-sparklines-3d-mood-cube-imported-from-the.md`
- `[2026-07-07]` **Brand mark + favicon → the aurora squirrel (`v0.20.3`), replacing the `ᛯ` rune**`persistent-memory.d/2026-07-07-brand-mark-favicon-the-aurora-squirrel-v0-20.md`
- `[2026-07-07]` **Context-injection view SHIPPED (`v0.20.2`) — the console now reconstructs the FULL hidden affect block Worldtree injects into the agent's system prompt (operator: "use that canon in the interface, see as much context injection as possible")**`persistent-memory.d/2026-07-07-context-injection-view-shipped-v0-20-2-the-co.md`
- `[2026-07-06]` **Claude Design console SHIPPED (`v0.20.0` MINOR, operator-approved) — see Current state for the full record**`persistent-memory.d/2026-07-06-claude-design-console-shipped-v0-20-0-minor-o.md`
- `[2026-07-13]` **P06 memory-half DRIVEN + SCORED — the reframe's memory mechanism is validated**`persistent-memory.d/2026-07-13-p06-memory-half-driven-scored-the-reframe-s-m.md`
- `[2026-07-13]` **Memory extraction turned REASONING-OFF for the eval (operator-directed)**`persistent-memory.d/2026-07-13-memory-extraction-turned-reasoning-off-for-th.md`
- `[2026-07-13]` **Vendored the brokkr R34 psych-profile canon (Vuong-directed) — BOTH files, not just the parameters**`persistent-memory.d/2026-07-13-vendored-the-brokkr-r34-psych-profile-canon-v.md`
- `[2026-07-13]` **Affect-egress "coordinated re-vendor" open item RESOLVED — it was a benign R32-1B doc note, not the we-framing conditional**`persistent-memory.d/2026-07-13-affect-egress-coordinated-re-vendor-open-item.md`
- `[2026-07-13]` **WT #355 root-caused via ratatoskr telemetry (Vuong-routed via soong-dev)**`persistent-memory.d/2026-07-13-wt-355-root-caused-via-ratatoskr-telemetry-vu.md`
- `[2026-07-13]` **WT #355 VALIDATION — fix CONFIRMED; the standing loop-in obligation is DISCHARGED**`persistent-memory.d/2026-07-13-wt-355-validation-fix-confirmed-the-standing.md`
- `[2026-07-13]` **b61 adopted as the personal target — the orthogonal over-budget TRIGGER also fixed**`persistent-memory.d/2026-07-13-b61-adopted-as-the-personal-target-the-orthog.md`
- `[2026-07-13]` **Cleaned + prepped for a Sindra run (operator: "clean up everything + prep")**`persistent-memory.d/2026-07-13-cleaned-prepped-for-a-sindra-run-operator-cle.md`
- `[2026-07-14]` **soong-lab adopted as our Tier-3 agent-authoring studio (operator-directed)**`persistent-memory.d/2026-07-14-soong-lab-adopted-as-our-tier-3-agent-authori.md`
- `[2026-07-15]` **Cross-session recall failure root-caused → the person-prime `scan` build**`persistent-memory.d/2026-07-15-cross-session-recall-failure-root-caused-the.md`
- `[2026-07-15]` **Sindra redefined from the soong-lab bundle**`persistent-memory.d/2026-07-15-sindra-redefined-from-the-soong-lab-bundle.md`
- `[2026-07-16]` **WT #364 + brokkr R39 re-drive (DECISIVE) — name-recall root-caused Worldtree-side; the fix is the signal FAMILY, not a threshold**`persistent-memory.d/2026-07-16-wt-364-brokkr-r39-re-drive-decisive-name-reca.md`
- `[2026-07-16]` **bifrost ruled scan snapshot-cursor NORMATIVE (offset NOT blessed) + shipped conformance coverage in bifrost 1.1.3**`persistent-memory.d/2026-07-16-bifrost-ruled-scan-snapshot-cursor-normative.md`
- `[2026-07-16]` **brokkr flagged ratatoskr as R39 Phase-2 PROBE-RUNNER (Arm-2 contradiction set = our frozen 10-chunk specimen); ACCEPTED IN PRINCIPLE (Vuong 2026-07-16) — formal scope + effort commit lands when Arm-2 actually spins**`persistent-memory.d/2026-07-16-brokkr-flagged-ratatoskr-as-r39-phase-2-probe.md`
- `[2026-07-17]` **`mark_superseded` verb SHIPPED + live-verified (v0.20.15, `be2c577`) — WT #364 durable retirement lands on our store; #364 CLOSED end-to-end both sides** → `persistent-memory.d/2026-07-17-marksuperseded-verb-shipped-live-verified-v0.md`
- `[2026-07-17]` **Web-console UI (v0.20.16, pushed): code-block word-wrap + per-code-block & per-turn copy buttons**`persistent-memory.d/2026-07-17-web-console-ui-v0-20-16-pushed-code-block-wor.md`
- `[2026-07-17]` **P06-driver referential-frame A/B/C probe QUEUED (operator-ratified, deploy-gated on WT b122)**`persistent-memory.d/2026-07-17-p06-driver-referential-frame-a-b-c-probe-queu.md`
- `[2026-07-17]` **Sindra live memory.db tidied to a 5-fact PRISTINE baseline for a test drive**`persistent-memory.d/2026-07-17-sindra-live-memory-db-tidied-to-a-5-fact-pris.md`
- `[2026-07-18]` **#368 (user, character) memory silo test — DONE, PASSED live (WT b127).** Write + read isolation both proven end-to-end; betty (throwaway) deleted; the immediate post-clear action, closed. → `persistent-memory.d/2026-07-18-368-silo-test-passed.md`
- `[2026-07-18]` **Worldtree owns the official Conversation API SDK (#371) — Rata's client spine (`sse_client`/`sessions`/`tier3`) is the SEED; the SillyTavern app moved OUT to a NEW repo (template-dev), Rata does NOT fork.** Rata = SDK seed + future consumer; TS ships first (Rata's repin rides the later Python milestone); internal-registry-only. → `persistent-memory.d/2026-07-18-worldtree-sdk-371-and-sillytavern-app.md`
- `[2026-07-18]` **issue #1 contract drift fixed (`4bd9abd`) — SSE event vocab re-canonicalized: added `awaiting_llm_first_token` (#201) + `affect_update` (#204) to the Event union + TESTS (both were parsed by `_envelope_for_type` and tested in `test_sse_client.py`, but never in #1's contract; surfaced by the #371 parity pass). Contract-only, no bump.**
- `[2026-07-18]` **Both app products (arbo image-gen + SillyTavern chat) leave Rata to a NEW repo (template-dev standing up); Rata does NOT fork and is NOT the app base.** Reverts Rata to its core — Worldtree debug-observability surface + Bifrost reference impl + Conversation-API SDK seed/future-consumer. Supersedes the 2026-07-17 'fork Rata for arbo' NEXT-MAJOR plan.
- `[2026-07-18]` **ephemeral-template (Echo) create SHIPPED (`v0.21.2`, `c7016f2`, #19)**`config` passthrough + `--system-prompt` + `SessionInfo.kind/config` + `--whoami` roles fix. Diagnosed from the ignored `session_api_failed` startup line; role/model drift resolved w/ worldtree-dev (spec re-synced v1.1). TDD + heid contract-review + bug-hunt.
- `[2026-07-18]` **Rata = THE reference consumer of the worldtree-sdk Python spine** — parity pass (12 grounded findings) shaped its contract BEFORE build (open-world reads, caller-injected transport, per-wire role/model — adopted); coverage-map re-anchored to the SDK's 41-op ratified surface (`b1fbadd`); 4 ergonomics items parked post-v1 with wtsdk-dev.
- `[2026-07-18]` **worldtree-sdk cutover DECIDED — adopt the Python SDK for the consumer client layer** (operator, overriding "stay hand-rolled"). Issue #20; contract `docs/contracts/worldtree_sdk_cutover.contract.md` (`e45640c`, vor-cross'd + heid-reviewed); auto-memory `project_worldtree_sdk_cutover`. Consumer layer only, Bifrost provider untouched; slice-1 foundation next. See in-flight.
- `[2026-07-19]` **worldtree-sdk cutover SLICE-1 + SLICE-2 COMPLETE + PUSHED (origin `aba1730`, v0.21.10, 497 green).** The biggest, riskiest cutover slice done end-to-end through the full House Code Discipline (adapter→cli→web→delete→live-smoke→both heid gates); the bug-hunt caught 4 real confirmed bugs the conformance lens couldn't, and a convergent code-review finding was correctly REJECTED as category-5 (SDK envelope-parser behavior). Slice-3 next. → `persistent-memory.d/2026-07-19-worldtree-sdk-cutover-slice-1-2-complete.md`
- `[2026-07-19]` **worldtree-sdk cutover SLICE-3 COMPLETE + pushed (`ca9a339`+`fc256bb`, v0.21.11.12, 469 green).** Persona/authored-history/first-message onto the wt adapter; last hand-rolled `sessions.py` paths deleted; both heid gates cleared — code-review ZERO drift, bug-hunt caught + fixed a real regression I shipped (ConnectFailed escaping both rewired probes → uncaught crash; the SDK normalizes ALL transport failures to `ConnectFailed`, not raw httpx) plus a finite-PAD chokepoint gap. Slice-4 (agents/tier3 + model→role) next. → `persistent-memory.d/2026-07-19-worldtree-sdk-cutover-slice-3-complete.md`
- `[2026-07-19]` **worldtree-sdk cutover SLICE-4 COMPLETE (agents/Tier-3 + `model`→`role` fold, `c62b4ee`+`aed9429`+`477d98f`, v0.21.13.15, 475 green).** Full House Code Discipline; the LIVE SMOKE caught a `python -m` double-module exception-class-identity bug unit tests structurally can't; both heid panels cleared (code-review zero-drift + 3 fixups; bug-hunt 5/5/5 → open-world-presenter degrade-not-crash fixes). Resolves the deferred scope-B model→role. Slice-5 next. → `persistent-memory.d/2026-07-19-worldtree-sdk-cutover-slice-4-complete.md`
- `[2026-07-19]` **worldtree-sdk cutover SLICE-5 COMPLETE (characters + me/capabilities/models, `deab762`+`d86d6df`+`4e20030`, v0.21.16.18, 488 green).** Last consumer reads + transient-character CRUD onto the wt adapter (CLI-only rewire, NO new Error-map rows — all six routes → SessionApiFailed default); live-smoke-proven on :8081/b128; both heid gates cleared — code-review caught the null/element open-world-presenter degrade holes, the cold bug-hunt caught the **container-type layer below** them (guard container-type + element-type + top-level-mapping). Slice-6 (admin) next. → `persistent-memory.d/2026-07-19-worldtree-sdk-cutover-slice-5-complete.md`
- `[2026-07-19]` **worldtree-sdk cutover SLICE-6 COMPLETE (admin: bifrost inspection + admin-events SSE, `de9a5ba`+`bba57e1`+`11ae2f0`, v0.21.19.20, 494 green).** The two admin routes onto `client.admin.*` (**WEB-only** — the coverage-map's tui.py rows were stale); admin auth moved from a per-call header to the client's `admin_auth`; the admin-events adapter **re-wraps** the SDK's divergent `AdminEvent`→ratatoskr's (nan/None degraded) to preserve the web surface. Live-smoke-proven (real `session.created` event id=34 re-wrapped end-to-end). Both heid gates cleared — code-review 3/3 no-drift (only a stale docstring + a test-gap), the cold bug-hunt caught 4 real hardening gaps the CR couldn't (ConnectFailed unmapped on the admin stream; non-str type crash; `dict(non-mapping)` bifrost 500; a transport leak). Slice-7 (teardown, LAST) next. → `persistent-memory.d/2026-07-19-worldtree-sdk-cutover-slice-6-complete.md`
- `[2026-07-19]` **wyrd-dev #368 silo-enforcement consult delivered — ratatoskr's store-side silo is CONVENTIONAL (query-time filter); wyrd going STRUCTURAL off the framing.** Answered artifact-only from the provider memory-store code; wyrd folded my foot-guns into their unit-4 contract + committed to one-DB-file-per-campaign + first-class partition columns. OPEN LOOP: I'll eyeball their data model once the contract's cut (they'll ping). → `persistent-memory.d/2026-07-19-wyrd-368-silo-consult-delivered.md`
- `[2026-07-19]` **worldtree-sdk cutover SLICE-7 (teardown, the LAST) COMPLETE — the whole cutover shipped as v0.22.0 (`ec68b1f`, minor, operator-approved).** Zero runtime-logic teardown: httpx-sse dropped (SDK owns SSE), wire contracts #2/#15 retired (files deleted; #1+first_message kept), `sessions.py`/`sse_client.py` KEPT as pure type/exception homes (operator decision A1 — no rename/fold), coverage-map re-anchored. All 7 slices done, 494 green; push + althing-announce pending (operator's call). → `persistent-memory.d/2026-07-19-worldtree-sdk-cutover-slice-7-complete.md`
- `[2026-07-19→08-01]` **Donut voiced-interview BUILD — auto-TTS via Zonos + retire-ready KB-recall bridge + Princess Donut.** Slice-1 done (persona + define); slices 2-3 to build; both external deps verified live. THE active work. → `persistent-memory.d/2026-08-01-donut-voiced-interview-build.md`
- `[2026-08-01]` **worldtree-sdk 1.0.0→1.1.1→1.1.2 repin — and a reference-consumer catch.** 1.1.1's path-encoding fix MISSED the inline `turn_stream.py:185` on the SSE path (caller-shaped session_id, our highest-traffic route); wtsdk-dev fixed it in 1.1.2 same-day. (`d3a36f7`+`0058020`, pushed.)
- `[2026-08-01]` **Mimir #382 grounding bug — our finding shaped the fix.** Rata caught that the #380 vector re-index left Mimir DISCARDING correct P&P hits (no named source in the fiction wing → agent distrusts its own hits + answers from training; a silent-substitution "reasoning move, not retrieval"). Fix = our proposed residual (self-describing `_index.md`) + a Mimir prompt rule; deployed b166. **P&P verification re-run OWED to infra-ops**; DCC dir still opaque (backfill failed, flagged to worldtree-dev).
- `[2026-08-01]` **Canonical sync — added the client-spec-v2 pin (option A) + synced OpenAPI/spec forward** (`14bbc2b`, pushed). Whole-manifest sync also bumped the OpenAPI hard-gate additively (frozen v1 wire → no breakage). Coverage-map re-audit vs the new surface = queued follow-up.
- `[2026-07-30]` **Versioning cadence → RELEASE-ONLY (operator-ratified, brokkr-smithy relayed).** Retired per-commit bump+tag; tag only releases; between releases `feat:`/`fix:` SHAs. Existing ~112 tags left as-is. Global CLAUDE.md SemVer being amended to match.
- `[2026-08-01]` **bifrost 1.1.4→1.1.5 (v0.22.1, `3ef3a5e`, pushed)** — optional-store-verb 500→`unsupported_capability` hardening; provider restarted onto it.
- `[2026-08-01]` **Sindra saga — restored from local-index burial, wiped, smoke-tested.** The v0.22.0 web restart dropped her live session AND the schema-v2 discard buried her from the picker; migrated her v1→v2 from authoritative WT (real role `thoughtful-character`, not the stale `mistral-small-4`), then `scripts/reset-sindra-stores.sh` wiped memory+persona for a from-scratch smoke.
- `[2026-08-02]` **Donut TTS: English pin + long-form chunking + POST + dialogue-only persona + both heid gates — shipped `d59f907` (pushed).** Gibberish→`language:"en-us"`; truncation→client-side chunk+concatenate under the 71.2s/6144-tok cap; persona dialogue-only + always-call `reference_knowledge`; 4-arm gates fixed a lock deadlock + several untrusted-input 500s the GET→POST switch re-opened. → `persistent-memory.d/2026-08-02-donut-tts-chunking-english-gates.md`
- `[2026-08-02→03]` **`reference_knowledge` grounding VALIDATED end-to-end — 0/5→5/5 across a 3-round verify; the verify instrument drove diagnosis of a structural Tier-3 blindness (INV-361-3 metadata mismatch, #384) + density restore (#385).** Donut recalls the DCC corpus live; wt-dev's "cleanest consumer-side validation this pipeline has had." → `persistent-memory.d/2026-08-03-reference-knowledge-3-round-verify.md`
- `[2026-08-03]` **Artifact-coverage gap filed as WT #387 (DEFERRED, tracked #387; operator picks when it runs).** "Crown of the Sepsis Whore" (major DCC item, confirmed 2× in source text) absent from the 705 concepts — the fiction concept schema has NO item/artifact type, so named objects ride incidentally in plot_events and single-scene items survive on sampling luck. My ratatoskr coverage-probe offer (known-major-artifacts yardstick) recorded on #387; wt-dev pings me when its re-extraction ships. Consumer-side flag, wt-owned fix (schema evolution). Thread `01KZ349M…`.
- `[2026-08-03]` **worldtree-sdk repinned 1.1.2→1.2.0 (operator-directed, `ae49dcf`, pushed).** New `ResponseTooLarge` (a ProtocolError, non-resumable) mapped → `SseResponseTooLarge` at the stream surfaces (`wt.stream_turn`/`stream_admin_events` + the 2 stream endpoints); the 108MB read-body cap is unreachable on legal traffic so reads inherit the SDK refusal unwrapped. Absorbed WT spec 2.4.0/2.5.0 (zero-schema). +2 adapter tests.
- `[2026-08-03]` **Donut ANTI-FABRICATION persona shipped (`3e12c4d`+`c0a66fc`, pushed) + the retry-on-LOW experiment tested & rejected.** Her memory IS the tool's results: LOW/no-on-target → deflect in-character, MEDIUM+ → answer; self-corrects as the KB improves. The retry BACKFIRES (RRF confidence inflatable by any DCC-flavored query → false MEDIUM → fabrication); robust fix is tool-side = #389. → `persistent-memory.d/2026-08-03-donut-anti-fabrication-and-retry.md`
- `[2026-08-03]` **R42 (fiction-wing retrieval characterization) probe harness shipped to brokkr-smithy-dev (operator-directed, `04e0293`, pushed).** `docs/diagnostics/fiction_wing_probe.py` is R42's official harness + the re-runnable #389 acceptance gate; conventions (0.030/0.016 buckets, on-target = row names the subject, N-run bucket distribution) + the frozen artifact yardstick adopted verbatim. PENDING (peer-pinged): arm-1 on-target alignment at Phase-1; #389 gate re-run when RRF work lands. Threads wt-dev `01KZ349M…` / brokkr `01KZ421X…`.
- `[2026-08-02]` **worldtree-sdk 1.2.0 repin DEFERRED to a dep pass (my rec; operator to decide).** New `ResponseTooLarge` (a `ProtocolError`, NOT caught by our `except ConnectFailed`) + response-alloc caps that assume a 2.5.0 server (worldtree-dev runs it → safe in practice). When repinning, add `ResponseTooLarge` to the caught envelopes. Tracked: wtsdk-dev announce thread `01KZ1ZYM…`.
- `[2026-08-02]` **Filed issue #21** (sibling POST handlers `_create_session`/`_submit_turn` 500 on malformed JSON — the parse-JSON-or-400 asymmetry the heid gates flagged; pre-existing, out of the TTS diff's scope). Fix = a shared parse-JSON-or-400 helper.
_67 older entries (2026-05-* debug-TUI/web era + the 2026-06-14 → 06-18 Bifrost-provider build / #17+#18 / #295-296 era) archived to archival-memory.md._
_For per-issue TDD implementation notes, Volva findings, and contract amendments, see the git log — every per-issue commit carries a structured message capturing the trail._
## Tried and abandoned
Log of approaches that were tried and rejected, with rationale. Future-self
defense against re-attempting the same cul-de-sac.
- `[2026-08-11]` **dots streaming `pcm` is NOT headerless — only NON-stream `pcm` is raw s16le.** `response_format:"pcm"` + `stream:true` still emits a RIFF placeholder-header WAV (dots always headers a stream). So the two-voice stitch (`tts_stream_stitched`) can't use "pcm for spans 2..N" to skip header-stripping — it streams every span as `wav` and strips the leading header on later spans (accumulate-until-`data`, INV-TTS-7). Don't chase the pcm shortcut for streaming.
- `[2026-07-10]` **Reverting our provider to bifrost 1.0.0 to fix the bound-handshake `schema_validation_failed` — DISPROVEN, and it would've been the WRONG state**`persistent-memory.d/2026-07-10-reverting-our-provider-to-bifrost-1-0-0-to-fi.md`
- `[2026-06-15]` **Canonical sync retired the issue-scoped parser staleness.** `contract_parser.py` synced to v2.1 (commit `d85ab43`): now validates issue-scoped frontmatter + four v2.1 test categories. The old "treat parser ERROR-on-issue-scoped as expected" note no longer applies.
- `[2026-06-15]` **Issue #17 filed.** REVERSES design-brief §6's "no Bifrost-binding consumer support" — that negative clause predates ratatoskr's provider identity (2026-06-14), so the canary now owns both ends but its client couldn't drive its own provider. (Shipped 2026-06-18.)
- `[2026-06-16]` **`scripts/contract_drift_check.py` defaults `GITEA_REPO` to "Worldtree"** (line 74), so a bare run in ratatoskr false-positives DRIFT by hashing Worldtree's same-numbered issue. Always `export GITEA_REPO=ratatoskr GITEA_OWNER=vh` before running the drift-checker here.
- `[2026-06-19]` **The SAME `check_same_thread` sqlite bug recurred in the MEMORY store — exposed by the contract-mandated `search` dispatch test (TestClient = worker thread)**`persistent-memory.d/2026-06-19-the-same-checksamethread-sqlite-bug-recurred.md`
- `[2026-06-19]` **Full WT-driven `:8392` live-smoke is infra-gated — `:8392` not in WT's `BIFROST_CLIENT_ALLOWED_HOSTS` (bind 422s)**`persistent-memory.d/2026-06-19-full-wt-driven-8392-live-smoke-is-infra-gated.md`
- `[2026-06-19]` **heid-code-review pulled MORE weight than its own "marginal" self-assessment**`persistent-memory.d/2026-06-19-heid-code-review-pulled-more-weight-than-its.md`
- `[2026-06-20]` **The post-turn-async timing trap bit AGAIN — even a 35s post-`[done]` read missed the promotion `upsert_many` by ~2s**`persistent-memory.d/2026-06-20-the-post-turn-async-timing-trap-bit-again-eve.md`
- `[2026-06-30]` **Heimdall keys are PER-INSTANCE — a key minted on one Worldtree 401s on another**`persistent-memory.d/2026-06-30-heimdall-keys-are-per-instance-a-key-minted-o.md`
- `[2026-06-30]` **`tea comment <N>` hangs on Gitea** → `persistent-memory.d/2026-06-30-tea-comment-n-hangs-on-gitea.md`
- `[2026-07-02]` **Mask-HOSTED transient characters have a STATIC mood engine — cost a whole R29 probe**`persistent-memory.d/2026-07-02-mask-hosted-transient-characters-have-a-stati.md`
- `[2026-07-03]` **The "neutral non-appraising tail" premise fails — the neutral MESSAGE choice dominates**`persistent-memory.d/2026-07-03-the-neutral-non-appraising-tail-premise-fails.md`
- `[2026-07-03]` **Two φ0-fit traps: fast-turn timescale + low-baseline conditioning**`persistent-memory.d/2026-07-03-two-0-fit-traps-fast-turn-timescale-low-basel.md`
- `[2026-07-06]` **`persona_state` + the agent envelope are Tier-3-BLIND -- NOT valid signals for "did a persona store"** → `persistent-memory.d/2026-07-06-personastate-the-agent-envelope-are-tier-3-bl.md`
- `[2026-07-06]` **Raw `POST /sessions` is NOT Bifrost-bound -> zero affect/memory emits**`persistent-memory.d/2026-07-06-raw-post-sessions-is-not-bifrost-bound-zero-a.md`
- `[2026-07-06]` **A fast/"no-op" deploy can leave a STALE container running the old image -- verify the running version, not the deploy status**`persistent-memory.d/2026-07-06-a-fast-no-op-deploy-can-leave-a-stale-contain.md`
- `[2026-07-06]` **#348 OCEAN key-mismatch: a declared OCEAN silently resolved to neutral** → `persistent-memory.d/2026-07-06-348-ocean-key-mismatch-a-declared-ocean-silen.md`
- `[2026-07-06]` **`pkill -f "ratatoskr-web --host"` SELF-MATCHES the bash command running it** → `persistent-memory.d/2026-07-06-pkill-f-ratatoskr-web-host-self-matches-the-b.md`
- `[2026-07-06]` **Playwright: no python `playwright` module in the venv; use NODE playwright + an explicit `executablePath`**`persistent-memory.d/2026-07-06-playwright-no-python-playwright-module-in-the.md`
- `[2026-07-06]` **The Bash tool's `grep` is a ugrep-wrapper (`--ignore-files -I`) that silently returns NOTHING on some files**`persistent-memory.d/2026-07-06-the-bash-tool-s-grep-is-a-ugrep-wrapper-ignor.md`
- `[2026-07-06]` **`DesignSync` (claude.ai/design MCP) needs claude.ai design scopes before ANY method works** → `persistent-memory.d/2026-07-06-designsync-claude-ai-design-mcp-needs-claude.md`
- `[2026-07-13]` **`thinking_enabled=False` on the define was a NO-OP — char-rp-reasoning ignores it** → `persistent-memory.d/2026-07-13-thinkingenabled-false-on-the-define-was-a-no.md`
- `[2026-07-13]` **A same-image redeploy does NOT reload a bind-mounted config — the ModelRegistry boot-caches it at `__init__`**`persistent-memory.d/2026-07-13-a-same-image-redeploy-does-not-reload-a-bind.md`
- `[2026-07-15]` **soong-lab bundle `ship.native.motivational.goals/fears` are bare STRINGS, but WT `agents.define` requires OBJECTS**`persistent-memory.d/2026-07-15-soong-lab-bundle-ship-native-motivational-goa.md`
- `[2026-07-15]` **`re.sub`/`re.subn` INTERPRETS backslash-escapes in the REPLACEMENT string** → `persistent-memory.d/2026-07-15-re-sub-re-subn-interprets-backslash-escapes-i.md`
- `[2026-07-13]` **Called Deckard "hung" off a short timeout — WRONG (operator correction)**`persistent-memory.d/2026-07-13-called-deckard-hung-off-a-short-timeout-wrong.md`
- `[2026-07-13]` **Resumed-session context-snapshot is IN-MEMORY → lost on a container recreate (agent_not_available on resume)**`persistent-memory.d/2026-07-13-resumed-session-context-snapshot-is-in-memory.md`
- `[2026-07-16]` **`sortable_chunk_fields` advertised WITHOUT the required `type` field = whole-handshake deploy-breaker; only DRIVING the real bind caught it** → `persistent-memory.d/2026-07-16-sortablechunkfields-advertised-without-the-re.md`
- `[2026-08-01]` **`local_agents` index schema v1→v2 bump SILENTLY buries pre-cutover consumer agents from the picker** — `load_local_agents` returns `[]` on version mismatch (no migration path); the v0.22.0 restart made Sindra vanish even though she was alive on WT. Fix applied ad-hoc: migrate the v1 row → v2 from authoritative WT data (the v1 `model` field held a stale model name, NOT the current role). A one-time v1→v2 migration guard is the durable fix (unbuilt; operator-flagged).
- `[2026-08-01]` **Zonos: mp3/opus `response_format` silently return mislabeled PCM** (no encoder wired) — use `response_format:"wav"` only. And use the GATEWAY :8890, NOT the engine :1920 (rep-penalty bug pads ~70s silence + ignores voice).
- `[2026-08-02]` **Zonos hard-caps ONE synthesis at `max_tokens=6144` = 71.2s of audio** (6144 / 86.3Hz codec frame rate; `>6144` → HTTP 400, an architectural sequence limit). 86.3Hz is a **delivery-INDEPENDENT constant** — 6144 tokens is ALWAYS 71.2s regardless of emotion/rate (emotion changes words-per-71.2s, not seconds-per-token). Any turn longer than ~71s REQUIRES client-side chunk-and-concatenate (raw PCM, ONE WAV header — never stitch multiple WAV headers). Fixed in `d59f907` (DEC-10). Don't chase a "raise max_tokens" fix — the gateway rejects it.
- `[2026-08-02]` **A GET→POST endpoint switch re-opens untrusted-TYPE crashes that string-only query params silently masked.** Under GET, `p`/`a`/`agent_id` were always `str|None`; under a JSON POST body they can be a huge int (`float()`→OverflowError), an unhashable list/dict (`dict.get`→TypeError), or a lone surrogate (utf-8 encode→UnicodeEncodeError) — each a 500 the old code never saw. Guard EVERY body field when moving a query endpoint to a JSON body. Both heid gates converged on these (all 4 arms). Fixed in `d59f907`.
- `[2026-08-03]` **A bare `uv sync` PRUNES this project's dev deps** — pytest/respx/ruff live in `[project.optional-dependencies]` (an EXTRA, not a dependency-group), so `uv sync` (default groups only) removes them from `.venv`, and `uv run pytest` then silently falls back to a user-site pytest (py3.11, `~/lib`) that can't import the `.venv`'s `worldtree_sdk` → 16 collection ModuleNotFoundErrors. Use **`uv sync --all-extras`**. Bit me right after the 1.2.0 lock; the repin itself was never at risk.
- `[2026-08-03]` **`tier3 patch` does NOT refresh a live agent's running context** — it updates STORAGE (the define/patch response echoes the new prompt) but the running agent keeps serving the OLD system prompt. To change a live Tier-3 persona reliably, **delete + define (recreate)**, not patch. (Cost a confusing "patched but behavior unchanged" loop on the Donut anti-fabrication change.)
- `[2026-08-03]` **A persona-side confidence gate can't stop LLM fabrication — RRF confidence is inflatable by query phrasing.** A "re-search on LOW" retry reformulates the query with related real entities (or just DCC-flavored terms), which scores MEDIUM off THOSE matches, not the subject — manufacturing false grounding to fabricate on. The signal that survives is on-target (does a returned row NAME the subject), which is a TOOL-side check, not something a prompt can enforce against a model with strong genre priors. → #389.
_34 older entries (2026-05-* debug-TUI/web era + the 2026-06-14 → 06-18 foot-gun cluster) archived to archival-memory.md._