memory: /snapshot — Worldtree SDK (#371) decision + issue-#1 drift fix
Capture this session's durable state: the "fork Rata for a SillyTavern-style app?" question resolved to don't-fork — Worldtree owns an official Conversation API SDK (WT #371), seeded from Rata's client spine; the app is a fresh TS sibling. New Current-state thread + Recent-decisions entries + a full-arc detail file; arbo-fork decision preserved with the arbo-vs-SDK priority flagged as an open operator question. Auto-archived 35 settled 2026-06-14..06-18 entries (19 Recent, 16 Tried) to archival-memory.md. Handoff refreshed.
This commit is contained in:
@@ -63,6 +63,85 @@ The 2026-05-20 → 2026-05-29 cluster: the original debug-TUI/web build era, bef
|
||||
- `[2026-06-15]` **Providers run as dev-box BACKGROUND SHELLS, not infra-ops/systemd** (operator call — it's a dev box). `ratatoskr-provider` (affect) + `ratatoskr-memory-provider` as background processes; no productionization track.
|
||||
_Archived 2026-07-17._
|
||||
|
||||
|
||||
The 2026-06-14 → 2026-06-18 cluster: the Bifrost-provider second-identity build era (#17/#18 self-drive+observe, #295/#296 cold-recall diagnosis, agent_self lattice). Archived 2026-07-18.
|
||||
|
||||
`[2026-06-15]` **Affect plane shipped (v0.17.2) + LIVE-PROVEN end-to-end against real Worldtree v0.35.2.** Personal handshake 200 + `affect.emit` 200 from `10.250.50.152` → durable row persisted (opacity held). HS256 key = the consumer's Heimdall API-key STRING utf-8-encoded (NOT base64/raw — the tripwire); cross-subnet route + `BIFROST_CLIENT_ALLOWED_HOSTS` allowlist all held (infra-ops-owned). worldtree-dev confirmed ADR-0009 holding as designed.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-16]` **#295 cold-recall miss root-caused — UPSTREAM, scope-axis asymmetry.** A self-driven bound cold-recall probe captured the inbound pair via the observe log: Worldtree's recall filter carries `{end_user, agent_self}`; our chunks were `{end_user}`-only; AND-matching dropped everything on `agent_self` → 0 hits. Our store + search are SOUND; fix is Worldtree-side. F2 (question-promotion) → **#296**; F1 (recall-miss) → **#297**.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-16]` **agent_self → make it CANONICAL (operator decided A).** bifrost's reference lattice was `{end_user, group, tenant}` only (agent_self → `invalid_filter` 400); Worldtree emits agent_self (#248). Operator chose canonical-not-re-expressed; worldtree-dev filed the lattice-addition with bifrost-dev. Implication: our store's permissive axis-acceptance becomes CORRECT once bifrost adds agent_self.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-16]` **Self-drive auth identity: bound session-create uses the CONSUMER Heimdall key as bearer, NOT `WORLDTREE_API_KEY`.** Worldtree signs the Bifrost handshake JWT with the session-create bearer (canary key → handshake 401; consumer key → 200). Two keys, two identities. Proven by hand; documented in `docs/bifrost-self-test.md`; load-bearing for #17's Bind half.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-16]` **Issue #17 v1 scope locked (operator 1A/2A): single-plane bind + dispatch-layer op-feed.** `BifrostBindingRequest` is one `endpoint_url` (one plane per session); composite-both-planes endpoint PARKED (→ now #18). Observe = structured op-feed at the DISPATCH layer (bifrost passes ctx to upsert_many but NOT search/get/delete — `memory.py:244`), session-level correlation; turn-correlated pane UI PARKED. Contract `docs/contracts/issues/17.contract.md` written + `/heid`-reviewed.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-16]` **agent_self lattice SHIPPED both sides → our axis-validation gap CLOSED (v0.17.5).** bifrost 0.7.0 / wire v0.5 adds agent_self to `{end_user,group,tenant,agent_self}` (#10, driven by our foot-gun flag); Worldtree pinned 0.7.0 (v0.35.11). We DID add `_validate_scope_filter` (4-axis) to match the reference (purely additive; out-of-lattice → InvalidFilter).
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-16]` **Repinned bifrost 0.7.0→0.8.0 + reimplemented memory `search` to the v0.6 scope split (operator-directed).** `scope_filter` → `scope_all` (AND) + `scope_any` (OR/union over a list of conjunctive scopes), bifrost #11 — the canonical resolution of the #295/#297 silent-zero. The reference now does OR via `scope_any` (a NEW field — additive split, not a flip of AND). Store / contract (v1.2) / tests at parity with the v0.6 reference; provider bounced onto 0.8.0 with a wiped DB. Shipped v0.17.6 (`96d61a4`). **(SUPERSEDED the earlier "do NOT flip `_scope_matches` to OR" note.)**
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-17]` **Worldtree spec pin bumped v0.29.0→v0.35.16 (`562001a`→`f1b59f8`); cold recall closed on the WIRE.** Worldtree shipped #297 (client-side per-scope-value union recall) + #298/#299 (adopt the bifrost v0.6 `scope_any`/`scope_all` wire) — emits `scope_any` on recall, pairing with our v0.17.6 provider. Re-vendored the spec; diff-reviewed the 285-commit catch-up — no client-breaking changes. `pin:`-only commit, no bump.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-17]` **End-to-end cold-recall proof RAN — our stack proven, #296 isolated.** Against personal WT v0.35.16 with restored `ratatoskr:sindra`: #297/#298 union recall, write path, and cold read ALL proven. Lone gap = upstream #296 extraction quality (the WIRE closed; fact-recall was #296-blocked).
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-17]` **DELETE+redefine `ratatoskr:sindra` (operator-authorized; pre-v1 debug surface).** She SURVIVED the rebuild but was STALE (dead model + no memory block); memory is immutable post-define, so DELETE+redefine was the only path. v0.35.16 define takes **`role`** (capability), NOT `model`: `role:"character"` → first-healthy bind `mistral-small-4`; `memory:{}` trips the promotion gate (GET does NOT echo `memory_config`). Our `tier3.py` define is Phase-2.0-stale — untracked modernization follow-up.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-17]` **Promotion = 4-trigger hybrid (worldtree-dev, code-grounded):** salience (regex, 90s rate-limit) / `turn_count≥6` / context_pressure / **idle `≥10min` (unconditional on quality)**; per-turn `plan_promotion_run` for consumer_defined. **DELETE does NOT drain/promote** (delete-is-delete, #276) — idle `≥10min` is the deterministic flush.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-18]` **#296 Stages 1+2 closed.** Stage 1 (v0.35.19, recallability admission gate) validated live for normal turns; bisect localized the residual to verbose-persona VOLUME crowd-out. Stage 2 (v0.36.0, MERGED at worldtree-codex) = user-only one-call-per-turn extraction, the STRUCTURAL fix; hard-linguistic layer → Worldtree #305 (we handed over a live-validated eval fixture PAIR). Full-coverage re-smoke: verbose `sindra-probe` promoted the fact cleanly + cold-recalled @ 0.694 under v0.36.0.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-18]` **#17 implemented end-to-end via direct in-session TDD** (6 patch bumps `v0.17.8`→`v0.17.13`, suite 470 green). Slice order: bind primitive → op-feed → CLI → TUI → web(server) → web(UI). Tests drive the REAL bifrost dispatch via minted JWTs (`bifrost.core.dispatch_jwt.mint_dispatch_jwt`) — the "test against the shipped lib" posture, not hand-mocked envelopes. Op-feed reads `session_id` off the dispatch JWT `sub` claim (the contract open-q, resolved YES at the ASGI layer where the JWT is always present — `bifrost.reference_server._dispatch_auth.DispatchContext.session_id = payload["sub"]`). bifrost wire facts captured in-code: memory envelope `{operation, args}`→`memory_result(**payload)`={success,...}; verbs bare (search/upsert_many/get/get_many/delete_many); affect `{operation:"affect.emit"}`→`{success,stored}`; error envelope `{code, message}`; scopes `memory:read|write`.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-18]` **#17 live-smoke PROVEN — the whole thesis validated.** A self-driven bound CLI session showed, from the PROVIDER side, exactly which memory ops a turn produced (2 recall searches, exact bound session_id, real union-recall scopes). Negative (canary→auth_rejected) NOT live-constructible (Tier-1 agents aren't memory-bindable; a wrong key for an owner-scoped agent fails at agent-auth before the handshake) — covered by the unit test + prior hand-proof.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-18]` **Fixed a pre-existing test-isolation bug exposed by the #17 CLI tests** (`0bebad7`): `test_no_textual_import` did a live `importlib.reload(ratatoskr.cli)` that mutated the shared module in place, breaking class identity (`isinstance`/`pytest.raises`) for every test ordered after it. The real check is the static source-grep; the reload was vestigial → removed. Lesson: never `importlib.reload` a shared module in a test without restoring it.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-18]` **#18 filed (composite endpoint + PAD read-endpoint) — DEFERRED, tracked at Gitea #18.** Two pieces: (1) a composite Bifrost facade (new port e.g. `:8392`) fronting BOTH `:8390`+`:8391` advertising both caps at handshake → one session binds both planes (un-parks the #17 open-q; bifrost reference_server already mounts both planes in one app → thin combined builder; needs per-plane failure-status + the op-feed deriving plane PER-REQUEST from the path instead of its fixed `plane` param). (2) a non-bifrost PAD read-endpoint on the affect provider (recommended over web-reads-`affect.db`-directly) → web persona pane renders PAD/valence from OUR `:8390` store. **Composite half APPROVED by operator ("A is correct"); contract-first next.** **Persona-telemetry diagnosis (verified):** affect bind persists PAD (vuong: pleasure +0.146, familiarity 0.18→0.59 over 8 turns) but the pane reads Tier-3-404 `persona_state` AND Tier-3 emits ZERO `affect_update` SSE (wire-verified) — both WT sources dead, so #18's PAD-display half is the only path. `affect.fetch` over bifrost is RESERVED/blocked but irrelevant (we own the store). Proposed: fast-track the PAD-display half now (awaiting operator go), keep composite contract-first.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-18]` **#18 SPLIT; Deliverable 1 (composite) routed to bifrost — Option C (operator).** D2 (PAD read-endpoint, our-side only) fast-tracked; D1 (composite `:8392` endpoint) routed to bifrost-dev to add a PUBLIC `build_combined_app` rather than hand-roll one from bifrost privates — because ratatoskr is a debug surface that must exercise the CANONICAL surface ("don't go off the reservation"). The Heid framing-panel had unanimously recommended hand-rolling (Option B) — DISCARDED as wrong-grounded (the panel lacked the canonical-surface principle; their own finding that B reaches external/underscore-private names actually vindicated C). bifrost-dev confirmed: clean additive minor (~`v0.9.0`), design locked (advertise-by-store-PRESENCE handshake — no health probe; per-route call-time isolation within a shared ASGI process), slotted after WT #289. [principle → auto-memory `feedback-debug-surface-uses-canonical-surface-only`]
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-18]` **FR-1 RESOLVED — the composite premise was unverified, now wire-proven: single-endpoint, caps-routed.** The Heid panel's sharpest catch (Regin): "advertise both caps → Worldtree dispatches both planes to one endpoint" was an ASSUMPTION about WT dispatch, stated as fact. worldtree-dev verified IN CODE: one `BifrostClient` per session (single `_endpoint_url`), handshake `capabilities_granted` parsed INDEPENDENTLY into memory+affect sets, both stores attach off the SAME endpoint iff their cap was granted (`service.py:2597/2703-2713/2745-2751`, `bifrost_client.py ~357-369`; tests `test_tier3_bifrost_{memory,affect}_routing.py`). So D1 is **bifrost-only, ZERO Worldtree change** — #18's "no WT change needed" assumption was correct.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-18]` **#18 D2 implemented via direct in-session TDD (suite 470→482).** Provider read route `GET /affect/state/{agent_id}` added via `app.add_route` (NOT an outer `Mount` — keeps `/bifrost/*` top-level so the existing route test + the op-feed path-check stay valid); web `GET /api/affect/{agent_id}` proxy (server-supplied `end_user_id`, colon-id `quote()`'d, `RATATOSKR_AFFECT_READ_URL`); pane renders the affect-emit shape honestly. Contract `docs/contracts/issues/18.contract.md` (D2-scoped; D1 deferred). **heid-code-review panel (Gróa 5 / Hulda 3 / Regin 0): 1 real INV-001 drift + 4 test-gaps, all fixed.** No contract amendments (code was wrong, contract was right).
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
## Tried and abandoned (archived)
|
||||
|
||||
The 2026-05-20 → 2026-05-28 cluster: original-build-era foot-guns. Archived 2026-06-18.
|
||||
@@ -85,3 +164,69 @@ The 2026-05-20 → 2026-05-28 cluster: original-build-era foot-guns. Archived 20
|
||||
- `[2026-05-27]` **`get_persona_state` mocked flat error envelope; real Worldtree wraps in `detail`.** v0.12.0 tests used `{"error_code": "auth_scope_denied"}` but real wire (FastAPI default) returns `{"detail": {"error_code": "auth_scope_denied", "message": "…"}}`. The parser only checked top-level so the typed exception was never raised; calls fell through to `SessionApiFailed(403)`, which the web persona endpoint surfaced as HTTP 500. v0.15.1 patches both shapes. **Lesson: test-side mock envelopes must match the REAL wire shape; live smoke is load-bearing for envelope-shape verification, not just happy paths.**
|
||||
- `[2026-05-27]` **Mid-session `system_prompt` mutation: universal omission across surveyed mature systems.** brokkr-smithy R13 panel (3-arm, strong convergence) confirmed: no surveyed system ships live PATCH-on-active-session (OpenAI Assistants/Responses, Anthropic Messages, Vertex AI, MCP, LangChain, LlamaIndex, Ollama, vLLM). The omission IS the answer. 12 additional threat vectors beyond ratatoskr's initial 7. **Don't re-propose this for ratatoskr;** if a future production conversational shell wants iterative-prompt-tuning ergonomics, the consensus shape is fork-via-client (PATCH agent → new session → replay context).
|
||||
- `[2026-05-28]` **Browser-local turn_id used for upstream cancel URL — old cancel tests ENCODED the bug.** Web companion v0.15.x cancel paths posted to `/sessions/{sid}/turns/{LOCAL_ID}/cancel`. Tests mocked the local-id URL so they encoded the bug rather than detecting it. Hulda caught it in Heid pass 1. Fix in v0.16.0: capture upstream_turn_id from the first SSE event's `sse_id.turn_id`; all cancel paths use it; cancel before first event is `{"cancelled": false, "reason": "not_started"}`. **Rule: when designing cancel/match paths against an external service, test fixtures must mock what would actually be hit upstream — mocking your own derived id encodes the bug instead of catching it.**
|
||||
|
||||
The 2026-06-14 → 2026-06-18 cluster (foot-guns from the same era). Archived 2026-07-18.
|
||||
|
||||
`[2026-06-14]` **Artifact-only contract review can't validate against a dependency's ACTUAL behavior.** `/heid-contract-review` sees only the contract, never the external library (bifrost) — so "the consumer under-built against bifrost's real semantics" is invisible to it by construction (the affect idempotency model shipped wrong because of this). Real-lib TDD against the shipped library + the executable reference store + the #195 parity test are the gate. Don't treat a clean contract review as evidence the code matches the dependency.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-15]` **"Sindra hasn't been registered" was an under-verified inference — WRONG.** Concluded it from grepping ratatoskr's CODE (`sindra` absent from `src/`), but Tier-3 registration is SERVER-SIDE (`POST /agents/define`) — a code grep structurally can't see it. **Rule: to check whether a Tier-3 agent exists, query the Worldtree instance, never the consumer repo's code.** (Extended 2026-06-17: even `GET /agents` can't see consumer agents; only `GET /agents/<owner>:<name>` with the owner key does.)
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-15]` **"byte-equal" round-trip slip propagated affect→memory via copy-paste.** The affect contract's byte-identical→semantic fix reappeared in the memory contract's INV-001 (sibling copy). Only an INDEPENDENT `/heid-contract-review` of the memory contract re-caught it. **Paraphrase every sibling contract fresh — don't amortize one review across a family; copies carry the parent's slips.** (also a feedback auto-memory)
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-15]` **Memory plane TDD'd + shipped** (commit `cd12951`, v0.17.3). Impl decisions worth keeping: vec0 `distance_metric=cosine` at table creation (`score = 1 − distance`); `search` over-fetches ALL candidates by cosine then scope-filters in Python so `top_k` counts IN-SCOPE hits; idempotency_id = reference 4-tuple `("default",verb,_ctx_actor(ctx),key)` pipe-joined as the SQLite PK, digest = sha256 canonical-JSON; `_ctx_actor` = `job_id|jwt_sub|session_id`. heid-code-review returned zero true drift; optimistic-lock semantics pinned to the reference via an `expected_revisions` parity test.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-15]` **Memory provider LIVE-PROVEN against personal v0.35.3; recall-injection is upstream.** worldtree-dev's Tier-3 promotion recipe: memory-call fires from Tier-3 PROMOTION, gated at `service.py:2623` on `ctx.kind=="consumer_defined"` AND `ctx.memory_config is not None` (agent DEFINED WITH a `memory` block, dim 1024) AND handshake-granted memory caps AND `embedding_dim==1024`. Binding = `POST /sessions BifrostBindingRequest{endpoint_url}`, handshake `caps=["affect","memory"]`, **`binding.scope` null** (per-op scopes auto-minted). A `BIFROST_CLIENT_ALLOWED_HOSTS` allowlist gates the endpoint (infra-ops added `:8391`). HTTP + HS256 both work in dev.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-15]` **Diagnostic: our recall-search is SOUND — the cross-session recall gap is UPSTREAM, and it caught an upstream bug.** Embedded the recall query via gateway `qwen3-embedding` + searched our live store directly → the fact recalls at cosine 0.60, correctly ranked. So the cold-session recall failure is Worldtree's recall-assembly/injection, NOT our search. ALSO found a latent UPSTREAM bug: a recall QUESTION got promoted as a durable chunk and ranked #1. **This is exactly #17's thesis — ratatoskr-as-provider caught an upstream bug invisible from the chat side.**
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-15]` **"Wire 200 ≠ recall works" — prove recall efficacy at the model's answer in a COLD (history-free) session, not on the wire.** A `search`/memory-call returns 200 whether or not its results are injected, and same-session "recall" can be plain session history. Don't call cross-session recall proven from a clean wire.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-16]` **My #295 coupling hypothesis (the promoted question crowds out the fact at small top_k) was REFUTED** — worldtree-dev's recall over-fetches `top_k=128`, so the question can't crowd the fact out at search level. The real cause was the scope-axis asymmetry. Lesson: offer provider-side hypotheses, let the upstream owner check them against their code.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-16]` **#17 contract drifted from its own design in two spots, caught only by `/heid-contract-review` (not same-author paraphrase):** the `OpEvent` dataclass omitted the `turn_id` INV-005 promised; a `session_id` comment contradicted the dispatch-layer design. Cross-model paraphrase is load-bearing for catching an author's own contract-vs-intent drift.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-16]` **"No promotion" was checked TOO EARLY — Tier-3 promotion is ASYNC (lands AFTER the SSE turn-end).** Don't trust an immediate post-turn fixture snapshot to judge promotion; it lands after the turn completes. (The reason #17's contract pins a post-turn grace window + fixture before/after assertion.)
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-17]` **"sindra is GONE" (infra-ops, from `GET /agents` + admin token) was a FALSE NEGATIVE.** Consumer-defined Tier-3 agents are OWNER-SCOPED (separate `consumer_agents` table) — invisible to the foundational `GET /agents` roster even with an admin token. To check, `GET /agents/<owner>:<name>` with the OWNER key.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-17]` **"Promotion didn't fire → #296" was PREMATURE — twice over.** (1) Polled the op-feed only ~2min, but the upsert landed at ~4min — promotion is async + multi-trigger; watch a longer window. (2) It DID fire; the real bug is extraction QUALITY, not non-firing. "No upsert while a session is live and `<10min` idle" is WAD.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-18]` **Wiping our `:8391` store does NOT reset Worldtree's promotion-side dedup** — a same-agent re-smoke returned `reason_code=noop_duplicate` / `candidate_count=0`: the extractor NEVER RE-RAN, dedup short-circuited against an earlier promotion. **For a clean promotion smoke, use a BRAND-NEW agent + end_user (never-used names).** (Also: `llm_calls_used=0` is NOT the "did the extractor run" tell — `noop_duplicate` is.)
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-18]` **`affect.emit` is POST-TURN ASYNC — checking the op-feed immediately after a turn MISSES it.** The Tier-3 affect appraise→emit→rehydrate loop runs AFTER the SSE `[done]`; the emit lands in our `:8390` store seconds later (op-feed grep right after `[done]` showed only the handshake; the `emit stored:true` appeared on a later read). Same family as the async-promotion timing trap. Watch a few-second window post-turn before concluding "no affect emitted." Also wire-verified the same turn: Tier-3 sindra emits ZERO `affect_update` SSE (the persona-strip SSE path never populates for consumer agents) — see the #18 PAD-display decision.
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-18]` **Rationalized away a KNOWN contract-invariant deviation during TDD — only the cross-model code-review caught it.** #18 D2's `loadAffect` called `setPersonaStrip(snap)`, which renders `dominant_emotion || "neutral"`; the affect snapshot has no `dominant_emotion`, so it fabricated a "neutral" emotion — violating the very INV-001 ("no synthesized Tier-1 fields") I had WRITTEN. I knew the strip did this and talked myself into it as acceptable. Neither the design panel nor TDD caught it (unit tests don't exercise the JS render); the post-implementation `/heid-code-review` did (Gróa + Hulda both). **Lesson: a known deviation from a contract invariant is drift even when you've rationalized it — flag it, don't argue yourself past it; the post-implementation cross-model review is the backstop for author-rationalized drift, distinct from the design-stage panel.**
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
`[2026-06-18]` **Latent SQLite thread-safety bug in the affect store, surfaced ONLY by the new HTTP read route.** `open_affect_store` created the connection without `check_same_thread=False`; the bifrost emit path never tripped it (uvicorn's loop ran on the connection's creating thread), but the `TestClient`-driven read route runs handlers off a worker thread → `sqlite3.ProgrammingError`. Fix: `check_same_thread=False` (safe — the event loop serializes access) + explicit `PRAGMA busy_timeout=5000` (don't rely on sqlite3's `timeout=5.0` default). **Lesson: a sqlite-backed ASGI app needs `check_same_thread=False`; the HTTP-layer test exposed what the direct-store-method tests structurally couldn't.**
|
||||
|
||||
_Archived 2026-07-18._
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-14]` **Artifact-only contract review can't validate against a dependency's ACTUAL behavior.** `/heid-contract-review` sees only the contract, never the external library (bifrost) — so "the consumer under-built against bifrost's real semantics" is invisible to it by construction (the affect idempotency model shipped wrong because of this). Real-lib TDD against the shipped library + the executable reference store + the #195 parity test are the gate. Don't treat a clean contract review as evidence the code matches the dependency.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-15]` **Affect plane shipped (v0.17.2) + LIVE-PROVEN end-to-end against real Worldtree v0.35.2.** Personal handshake 200 + `affect.emit` 200 from `10.250.50.152` → durable row persisted (opacity held). HS256 key = the consumer's Heimdall API-key STRING utf-8-encoded (NOT base64/raw — the tripwire); cross-subnet route + `BIFROST_CLIENT_ALLOWED_HOSTS` allowlist all held (infra-ops-owned). worldtree-dev confirmed ADR-0009 holding as designed.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-15]` **"byte-equal" round-trip slip propagated affect→memory via copy-paste.** The affect contract's byte-identical→semantic fix reappeared in the memory contract's INV-001 (sibling copy). Only an INDEPENDENT `/heid-contract-review` of the memory contract re-caught it. **Paraphrase every sibling contract fresh — don't amortize one review across a family; copies carry the parent's slips.** (also a feedback auto-memory)
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-15]` **Diagnostic: our recall-search is SOUND — the cross-session recall gap is UPSTREAM, and it caught an upstream bug.** Embedded the recall query via gateway `qwen3-embedding` + searched our live store directly → the fact recalls at cosine 0.60, correctly ranked. So the cold-session recall failure is Worldtree's recall-assembly/injection, NOT our search. ALSO found a latent UPSTREAM bug: a recall QUESTION got promoted as a durable chunk and ranked #1. **This is exactly #17's thesis — ratatoskr-as-provider caught an upstream bug invisible from the chat side.**
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-15]` **Memory plane TDD'd + shipped** (commit `cd12951`, v0.17.3). Impl decisions worth keeping: vec0 `distance_metric=cosine` at table creation (`score = 1 − distance`); `search` over-fetches ALL candidates by cosine then scope-filters in Python so `top_k` counts IN-SCOPE hits; idempotency_id = reference 4-tuple `("default",verb,_ctx_actor(ctx),key)` pipe-joined as the SQLite PK, digest = sha256 canonical-JSON; `_ctx_actor` = `job_id|jwt_sub|session_id`. heid-code-review returned zero true drift; optimistic-lock semantics pinned to the reference via an `expected_revisions` parity test.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-15]` **Memory provider LIVE-PROVEN against personal v0.35.3; recall-injection is upstream.** worldtree-dev's Tier-3 promotion recipe: memory-call fires from Tier-3 PROMOTION, gated at `service.py:2623` on `ctx.kind=="consumer_defined"` AND `ctx.memory_config is not None` (agent DEFINED WITH a `memory` block, dim 1024) AND handshake-granted memory caps AND `embedding_dim==1024`. Binding = `POST /sessions BifrostBindingRequest{endpoint_url}`, handshake `caps=["affect","memory"]`, **`binding.scope` null** (per-op scopes auto-minted). A `BIFROST_CLIENT_ALLOWED_HOSTS` allowlist gates the endpoint (infra-ops added `:8391`). HTTP + HS256 both work in dev.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-15]` **"Sindra hasn't been registered" was an under-verified inference — WRONG.** Concluded it from grepping ratatoskr's CODE (`sindra` absent from `src/`), but Tier-3 registration is SERVER-SIDE (`POST /agents/define`) — a code grep structurally can't see it. **Rule: to check whether a Tier-3 agent exists, query the Worldtree instance, never the consumer repo's code.** (Extended 2026-06-17: even `GET /agents` can't see consumer agents; only `GET /agents/<owner>:<name>` with the owner key does.)
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-15]` **"Wire 200 ≠ recall works" — prove recall efficacy at the model's answer in a COLD (history-free) session, not on the wire.** A `search`/memory-call returns 200 whether or not its results are injected, and same-session "recall" can be plain session history. Don't call cross-session recall proven from a clean wire.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-16]` **#17 contract drifted from its own design in two spots, caught only by `/heid-contract-review` (not same-author paraphrase):** the `OpEvent` dataclass omitted the `turn_id` INV-005 promised; a `session_id` comment contradicted the dispatch-layer design. Cross-model paraphrase is load-bearing for catching an author's own contract-vs-intent drift.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-16]` **#295 cold-recall miss root-caused — UPSTREAM, scope-axis asymmetry.** A self-driven bound cold-recall probe captured the inbound pair via the observe log: Worldtree's recall filter carries `{end_user, agent_self}`; our chunks were `{end_user}`-only; AND-matching dropped everything on `agent_self` → 0 hits. Our store + search are SOUND; fix is Worldtree-side. F2 (question-promotion) → **#296**; F1 (recall-miss) → **#297**.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-16]` **agent_self lattice SHIPPED both sides → our axis-validation gap CLOSED (v0.17.5).** bifrost 0.7.0 / wire v0.5 adds agent_self to `{end_user,group,tenant,agent_self}` (#10, driven by our foot-gun flag); Worldtree pinned 0.7.0 (v0.35.11). We DID add `_validate_scope_filter` (4-axis) to match the reference (purely additive; out-of-lattice → InvalidFilter).
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-16]` **agent_self → make it CANONICAL (operator decided A).** bifrost's reference lattice was `{end_user, group, tenant}` only (agent_self → `invalid_filter` 400); Worldtree emits agent_self (#248). Operator chose canonical-not-re-expressed; worldtree-dev filed the lattice-addition with bifrost-dev. Implication: our store's permissive axis-acceptance becomes CORRECT once bifrost adds agent_self.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-16]` **Issue #17 v1 scope locked (operator 1A/2A): single-plane bind + dispatch-layer op-feed.** `BifrostBindingRequest` is one `endpoint_url` (one plane per session); composite-both-planes endpoint PARKED (→ now #18). Observe = structured op-feed at the DISPATCH layer (bifrost passes ctx to upsert_many but NOT search/get/delete — `memory.py:244`), session-level correlation; turn-correlated pane UI PARKED. Contract `docs/contracts/issues/17.contract.md` written + `/heid`-reviewed.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-16]` **My #295 coupling hypothesis (the promoted question crowds out the fact at small top_k) was REFUTED** — worldtree-dev's recall over-fetches `top_k=128`, so the question can't crowd the fact out at search level. The real cause was the scope-axis asymmetry. Lesson: offer provider-side hypotheses, let the upstream owner check them against their code.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-16]` **"No promotion" was checked TOO EARLY — Tier-3 promotion is ASYNC (lands AFTER the SSE turn-end).** Don't trust an immediate post-turn fixture snapshot to judge promotion; it lands after the turn completes. (The reason #17's contract pins a post-turn grace window + fixture before/after assertion.)
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-16]` **Repinned bifrost 0.7.0→0.8.0 + reimplemented memory `search` to the v0.6 scope split (operator-directed).** `scope_filter` → `scope_all` (AND) + `scope_any` (OR/union over a list of conjunctive scopes), bifrost #11 — the canonical resolution of the #295/#297 silent-zero. The reference now does OR via `scope_any` (a NEW field — additive split, not a flip of AND). Store / contract (v1.2) / tests at parity with the v0.6 reference; provider bounced onto 0.8.0 with a wiped DB. Shipped v0.17.6 (`96d61a4`). **(SUPERSEDED the earlier "do NOT flip `_scope_matches` to OR" note.)**
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-16]` **Self-drive auth identity: bound session-create uses the CONSUMER Heimdall key as bearer, NOT `WORLDTREE_API_KEY`.** Worldtree signs the Bifrost handshake JWT with the session-create bearer (canary key → handshake 401; consumer key → 200). Two keys, two identities. Proven by hand; documented in `docs/bifrost-self-test.md`; load-bearing for #17's Bind half.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-17]` **DELETE+redefine `ratatoskr:sindra` (operator-authorized; pre-v1 debug surface).** She SURVIVED the rebuild but was STALE (dead model + no memory block); memory is immutable post-define, so DELETE+redefine was the only path. v0.35.16 define takes **`role`** (capability), NOT `model`: `role:"character"` → first-healthy bind `mistral-small-4`; `memory:{}` trips the promotion gate (GET does NOT echo `memory_config`). Our `tier3.py` define is Phase-2.0-stale — untracked modernization follow-up.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-17]` **End-to-end cold-recall proof RAN — our stack proven, #296 isolated.** Against personal WT v0.35.16 with restored `ratatoskr:sindra`: #297/#298 union recall, write path, and cold read ALL proven. Lone gap = upstream #296 extraction quality (the WIRE closed; fact-recall was #296-blocked).
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-17]` **Promotion = 4-trigger hybrid (worldtree-dev, code-grounded):** salience (regex, 90s rate-limit) / `turn_count≥6` / context_pressure / **idle `≥10min` (unconditional on quality)**; per-turn `plan_promotion_run` for consumer_defined. **DELETE does NOT drain/promote** (delete-is-delete, #276) — idle `≥10min` is the deterministic flush.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-17]` **"Promotion didn't fire → #296" was PREMATURE — twice over.** (1) Polled the op-feed only ~2min, but the upsert landed at ~4min — promotion is async + multi-trigger; watch a longer window. (2) It DID fire; the real bug is extraction QUALITY, not non-firing. "No upsert while a session is live and `<10min` idle" is WAD.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-17]` **"sindra is GONE" (infra-ops, from `GET /agents` + admin token) was a FALSE NEGATIVE.** Consumer-defined Tier-3 agents are OWNER-SCOPED (separate `consumer_agents` table) — invisible to the foundational `GET /agents` roster even with an admin token. To check, `GET /agents/<owner>:<name>` with the OWNER key.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-17]` **Worldtree spec pin bumped v0.29.0→v0.35.16 (`562001a`→`f1b59f8`); cold recall closed on the WIRE.** Worldtree shipped #297 (client-side per-scope-value union recall) + #298/#299 (adopt the bifrost v0.6 `scope_any`/`scope_all` wire) — emits `scope_any` on recall, pairing with our v0.17.6 provider. Re-vendored the spec; diff-reviewed the 285-commit catch-up — no client-breaking changes. `pin:`-only commit, no bump.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-18]` **#17 implemented end-to-end via direct in-session TDD** (6 patch bumps `v0.17.8`→`v0.17.13`, suite 470 green). Slice order: bind primitive → op-feed → CLI → TUI → web(server) → web(UI). Tests drive the REAL bifrost dispatch via minted JWTs (`bifrost.core.dispatch_jwt.mint_dispatch_jwt`) — the "test against the shipped lib" posture, not hand-mocked envelopes. Op-feed reads `session_id` off the dispatch JWT `sub` claim (the contract open-q, resolved YES at the ASGI layer where the JWT is always present — `bifrost.reference_server._dispatch_auth.DispatchContext.session_id = payload["sub"]`). bifrost wire facts captured in-code: memory envelope `{operation, args}`→`memory_result(**payload)`={success,...}; verbs bare (search/upsert_many/get/get_many/delete_many); affect `{operation:"affect.emit"}`→`{success,stored}`; error envelope `{code, message}`; scopes `memory:read|write`.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-18]` **#17 live-smoke PROVEN — the whole thesis validated.** A self-driven bound CLI session showed, from the PROVIDER side, exactly which memory ops a turn produced (2 recall searches, exact bound session_id, real union-recall scopes). Negative (canary→auth_rejected) NOT live-constructible (Tier-1 agents aren't memory-bindable; a wrong key for an owner-scoped agent fails at agent-auth before the handshake) — covered by the unit test + prior hand-proof.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-18]` **#18 D2 implemented via direct in-session TDD (suite 470→482).** Provider read route `GET /affect/state/{agent_id}` added via `app.add_route` (NOT an outer `Mount` — keeps `/bifrost/*` top-level so the existing route test + the op-feed path-check stay valid); web `GET /api/affect/{agent_id}` proxy (server-supplied `end_user_id`, colon-id `quote()`'d, `RATATOSKR_AFFECT_READ_URL`); pane renders the affect-emit shape honestly. Contract `docs/contracts/issues/18.contract.md` (D2-scoped; D1 deferred). **heid-code-review panel (Gróa 5 / Hulda 3 / Regin 0): 1 real INV-001 drift + 4 test-gaps, all fixed.** No contract amendments (code was wrong, contract was right).
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-18]` **#18 filed (composite endpoint + PAD read-endpoint) — DEFERRED, tracked at Gitea #18.** Two pieces: (1) a composite Bifrost facade (new port e.g. `:8392`) fronting BOTH `:8390`+`:8391` advertising both caps at handshake → one session binds both planes (un-parks the #17 open-q; bifrost reference_server already mounts both planes in one app → thin combined builder; needs per-plane failure-status + the op-feed deriving plane PER-REQUEST from the path instead of its fixed `plane` param). (2) a non-bifrost PAD read-endpoint on the affect provider (recommended over web-reads-`affect.db`-directly) → web persona pane renders PAD/valence from OUR `:8390` store. **Composite half APPROVED by operator ("A is correct"); contract-first next.** **Persona-telemetry diagnosis (verified):** affect bind persists PAD (vuong: pleasure +0.146, familiarity 0.18→0.59 over 8 turns) but the pane reads Tier-3-404 `persona_state` AND Tier-3 emits ZERO `affect_update` SSE (wire-verified) — both WT sources dead, so #18's PAD-display half is the only path. `affect.fetch` over bifrost is RESERVED/blocked but irrelevant (we own the store). Proposed: fast-track the PAD-display half now (awaiting operator go), keep composite contract-first.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-18]` **#18 SPLIT; Deliverable 1 (composite) routed to bifrost — Option C (operator).** D2 (PAD read-endpoint, our-side only) fast-tracked; D1 (composite `:8392` endpoint) routed to bifrost-dev to add a PUBLIC `build_combined_app` rather than hand-roll one from bifrost privates — because ratatoskr is a debug surface that must exercise the CANONICAL surface ("don't go off the reservation"). The Heid framing-panel had unanimously recommended hand-rolling (Option B) — DISCARDED as wrong-grounded (the panel lacked the canonical-surface principle; their own finding that B reaches external/underscore-private names actually vindicated C). bifrost-dev confirmed: clean additive minor (~`v0.9.0`), design locked (advertise-by-store-PRESENCE handshake — no health probe; per-route call-time isolation within a shared ASGI process), slotted after WT #289. [principle → auto-memory `feedback-debug-surface-uses-canonical-surface-only`]
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-18]` **#296 Stages 1+2 closed.** Stage 1 (v0.35.19, recallability admission gate) validated live for normal turns; bisect localized the residual to verbose-persona VOLUME crowd-out. Stage 2 (v0.36.0, MERGED at worldtree-codex) = user-only one-call-per-turn extraction, the STRUCTURAL fix; hard-linguistic layer → Worldtree #305 (we handed over a live-validated eval fixture PAIR). Full-coverage re-smoke: verbose `sindra-probe` promoted the fact cleanly + cold-recalled @ 0.694 under v0.36.0.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-18]` **`affect.emit` is POST-TURN ASYNC — checking the op-feed immediately after a turn MISSES it.** The Tier-3 affect appraise→emit→rehydrate loop runs AFTER the SSE `[done]`; the emit lands in our `:8390` store seconds later (op-feed grep right after `[done]` showed only the handshake; the `emit stored:true` appeared on a later read). Same family as the async-promotion timing trap. Watch a few-second window post-turn before concluding "no affect emitted." Also wire-verified the same turn: Tier-3 sindra emits ZERO `affect_update` SSE (the persona-strip SSE path never populates for consumer agents) — see the #18 PAD-display decision.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-18]` **Fixed a pre-existing test-isolation bug exposed by the #17 CLI tests** (`0bebad7`): `test_no_textual_import` did a live `importlib.reload(ratatoskr.cli)` that mutated the shared module in place, breaking class identity (`isinstance`/`pytest.raises`) for every test ordered after it. The real check is the static source-grep; the reload was vestigial → removed. Lesson: never `importlib.reload` a shared module in a test without restoring it.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-18]` **FR-1 RESOLVED — the composite premise was unverified, now wire-proven: single-endpoint, caps-routed.** The Heid panel's sharpest catch (Regin): "advertise both caps → Worldtree dispatches both planes to one endpoint" was an ASSUMPTION about WT dispatch, stated as fact. worldtree-dev verified IN CODE: one `BifrostClient` per session (single `_endpoint_url`), handshake `capabilities_granted` parsed INDEPENDENTLY into memory+affect sets, both stores attach off the SAME endpoint iff their cap was granted (`service.py:2597/2703-2713/2745-2751`, `bifrost_client.py ~357-369`; tests `test_tier3_bifrost_{memory,affect}_routing.py`). So D1 is **bifrost-only, ZERO Worldtree change** — #18's "no WT change needed" assumption was correct.
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-18]` **Latent SQLite thread-safety bug in the affect store, surfaced ONLY by the new HTTP read route.** `open_affect_store` created the connection without `check_same_thread=False`; the bifrost emit path never tripped it (uvicorn's loop ran on the connection's creating thread), but the `TestClient`-driven read route runs handlers off a worker thread → `sqlite3.ProgrammingError`. Fix: `check_same_thread=False` (safe — the event loop serializes access) + explicit `PRAGMA busy_timeout=5000` (don't rely on sqlite3's `timeout=5.0` default). **Lesson: a sqlite-backed ASGI app needs `check_same_thread=False`; the HTTP-layer test exposed what the direct-store-method tests structurally couldn't.**
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-18]` **Rationalized away a KNOWN contract-invariant deviation during TDD — only the cross-model code-review caught it.** #18 D2's `loadAffect` called `setPersonaStrip(snap)`, which renders `dominant_emotion || "neutral"`; the affect snapshot has no `dominant_emotion`, so it fabricated a "neutral" emotion — violating the very INV-001 ("no synthesized Tier-1 fields") I had WRITTEN. I knew the strip did this and talked myself into it as acceptable. Neither the design panel nor TDD caught it (unit tests don't exercise the JS render); the post-implementation `/heid-code-review` did (Gróa + Hulda both). **Lesson: a known deviation from a contract invariant is drift even when you've rationalized it — flag it, don't argue yourself past it; the post-implementation cross-model review is the backstop for author-rationalized drift, distinct from the design-stage panel.**
|
||||
@@ -1 +0,0 @@
|
||||
`[2026-06-18]` **Wiping our `:8391` store does NOT reset Worldtree's promotion-side dedup** — a same-agent re-smoke returned `reason_code=noop_duplicate` / `candidate_count=0`: the extractor NEVER RE-RAN, dedup short-circuited against an earlier promotion. **For a clean promotion smoke, use a BRAND-NEW agent + end_user (never-used names).** (Also: `llm_calls_used=0` is NOT the "did the extractor run" tell — `noop_duplicate` is.)
|
||||
@@ -0,0 +1,81 @@
|
||||
`[2026-07-18]` **Worldtree owns the official Conversation API SDK (#371); the SillyTavern-style app is a fresh TS sibling, NOT a fork of Rata.**
|
||||
|
||||
## The question that started it
|
||||
|
||||
Operator: "I want to create an app like SillyTavern that runs on Worldtree. Ratatoskr
|
||||
is already most of the way there, so I'm thinking we fork it." → turned into a
|
||||
structural decision about how a new Worldtree chat product should relate to Rata.
|
||||
|
||||
## Why NOT fork Rata
|
||||
|
||||
Rata splits into three layers: (1) a **Worldtree client spine** (~1.8k LOC —
|
||||
`sse_client.py` SSE/resume, `sessions.py` session/agent/persona clients, `tier3.py`
|
||||
agent lifecycle); (2) a Bifrost **provider** layer (`provider/*`); (3) thin
|
||||
**front-ends** (debug web console + `--send` CLI). The reusable part is the client
|
||||
spine; the part that diverges is the front-end — and Rata's front-end is a
|
||||
*debug-observability console* you'd throw away for a chat product. **Forking gives
|
||||
you the wrong 60% and makes you delete it**, and muddies Rata's reference-impl
|
||||
identity. The ecosystem norm is already independent spec-pinned siblings (Skaldsong
|
||||
Python, mead-hall TS, Rata) — not forks.
|
||||
|
||||
## The decision (operator ruled YES 2026-07-17, via worldtree-dev)
|
||||
|
||||
- **Worldtree owns an official Conversation API client SDK** — spec-author-ships-the-SDK
|
||||
(Stripe/GitHub shape), keeps SDK↔spec in lockstep, avoids consumer-depends-on-peer-consumer
|
||||
coupling.
|
||||
- **Dedicated repo** (name settled at WT's shape pass), **elevated onto Worldtree's pre-v1
|
||||
work track** (NOT parked behind WT's two v1 pillars — agent bus + KB).
|
||||
- **Shape:** TS-first (near-term demand); types/CRUD generated from WT's published OpenAPI
|
||||
(`worldtree-conversation-api-openapi-v2`) + a hand-written SSE/resume/error spine **seeded
|
||||
from Rata's `sse_client`/`sessions`/`tier3`**. TS+Python same-source keeps them in sync.
|
||||
**Internal-registry-only distribution, permanently.**
|
||||
- **TS package ships v0 first, Python the following milestone** → **Rata's own repin rides
|
||||
the Python milestone** (not imminent; no schedule pressure on us).
|
||||
- **SillyTavern-style chat app = fresh TS sibling** consuming the SDK, NOT a fork of Rata.
|
||||
**template-dev stands up the app repo.** Its early TS client is the natural **seed for the
|
||||
SDK's TS side** (Rata seeds Python, the app seeds TS) — so it isn't throwaway.
|
||||
- **Bifrost held OUT of scope:** the provider Protocols already ship in the `bifrost` package;
|
||||
Rata's `provider/*` is a reference *provider* (a different, smaller audience). Separate track
|
||||
if ever warranted.
|
||||
|
||||
## Rata's contributions this session
|
||||
|
||||
- **Parity-matrix usage inventory** shipped to worldtree-dev (18 routes; SSE event/resume/
|
||||
heartbeat surface; full error-code → typed-exception table; auth scopes; **8 compat hacks
|
||||
that must survive the repin**). The load-bearing one: **empty-`id` SSE frames treated as
|
||||
keepalives** (a provider emits id-less events mid-stream — re-strictifying id parsing crashes
|
||||
turns on it) → promoted to normative rule **B-KA-2** in WT's behavioral spec. W-4 (tier-3
|
||||
`role`/`model` drift) triggered a Worldtree-side spec fixup. Seeded WT `docs/sdk/parity-matrix.md`
|
||||
(`698cfc3`), behavioral-spec (`c999b5f`).
|
||||
- **Fixture-corpus gap caught** (verified, then sent): `issues/1.contract.md`'s TESTS predate
|
||||
`awaiting_llm_first_token` (#201) + `affect_update` (#204) — its `full_event_vocab` stops at
|
||||
the 8-event set. WT confirmed and patched the fixture-checklist (`87d2569`) to seed from
|
||||
`_envelope_for_type` (authoritative 11-variant parse surface), not #1 alone. WT fixture corpus
|
||||
landed independently: `3019ee6`, 66 fixtures, validator clean.
|
||||
- **issue-#1 contract drift fixed our side** (`4bd9abd`) — re-canonicalized the SSE event vocab
|
||||
(added both events to the Event union + TESTS via a dated amendment; docs-only, no bump).
|
||||
- **Personal-WT endpoint shipped** for fixture/conformance capture: `http://10.250.50.152:8081`
|
||||
(health-checked live; unified error envelope = current-gen deploy). No key provisioning needed
|
||||
(operator env carries instance keys). **Capture run waits on explicit operator go + instance
|
||||
choice (demo :8080 vs personal :8081).**
|
||||
|
||||
## Pinned for our eventual repin (SDK diverges from Rata in 3 spots)
|
||||
|
||||
- **D-1** — unknown SSE event `type` → **skip with a diagnostics hook**, vs Rata's current hard
|
||||
`ValueError` in `_envelope_for_type`. Adopt only at repin.
|
||||
- **D-2** — open-world enums.
|
||||
- **D-3** — typed eager `410 session_retired`.
|
||||
|
||||
## Open question (operator)
|
||||
|
||||
How does this relate to the **arbo image-gen fork** (NEXT-MAJOR, 2026-07-17)? Different products
|
||||
(arbo = image-gen off ComfyUI's REST API; SillyTavern = chat off Worldtree), so no literal
|
||||
conflict — but this session established a don't-fork/fresh-sibling pattern for Worldtree consumers.
|
||||
Is SillyTavern/SDK now the priority app, additive to arbo, or does the pattern change the arbo
|
||||
plan? NOT resolved; both preserved in Current state.
|
||||
|
||||
## Tracking
|
||||
|
||||
Worldtree **#371** (their tracking issue). Rata-side: contract fix `4bd9abd`. Cross-references:
|
||||
[[2026-07-18-368-silo-test-passed]] (the prior arc), the reference-impl posture (auto-memory
|
||||
`feedback_ratatoskr_is_a_reference_impl_adopt_canonical`).
|
||||
+72
-114
@@ -46,118 +46,89 @@ upstream API key stays server-side (INV-003).
|
||||
|
||||
_As of 2026-07-18:_
|
||||
|
||||
**✅ #368 (user, character) MEMORY SILO TEST — DONE, PASSED LIVE (2026-07-18, WT b127).** The reason for the clear;
|
||||
now closed. Silo holds end-to-end: write-side promoted chunks carry conjunctive `{end_user, agent_self}` (proven on
|
||||
3 live Sindra promotions under end_user `silo-368`); read-side isolation proven by cold-recall (fresh Betty session,
|
||||
SAME end_user, got ZERO hits → "I don't know", did NOT bleed Sindra's coffee; Sindra recalled her own coffee).
|
||||
Migration sentinel `worldtree:migration:agent-scope-v1` written on first bind (backfill a no-op on the born-empty
|
||||
store). Zero consumer changes, as contracted. Throwaway `ratatoskr:betty` DELETED (WT + local); Sindra intact. Full
|
||||
record → `persistent-memory.d/2026-07-18-368-silo-test-passed.md`. **Still QUEUED:** the backfill live-verify
|
||||
(synthetic legacy corpus — exercises the backfill machinery a born-fresh store skips).
|
||||
**▶️ NEW MAJOR — Worldtree Conversation API SDK (#371) + a SillyTavern-style chat app.**
|
||||
Operator wants a SillyTavern-like chat app on Worldtree; the "fork Rata?" question resolved to
|
||||
**don't fork**. Instead: **Worldtree owns an official Conversation API client SDK** (dedicated repo,
|
||||
elevated onto WT's pre-v1 track, tracking issue **WT #371**), **seeded from Rata's client spine**
|
||||
(`sse_client`/`sessions`/`tier3`); the chat app is a **fresh TS SIBLING** consuming that SDK, NOT a
|
||||
fork of Rata. TS package ships first — **Rata's own repin rides the later Python milestone**;
|
||||
internal-registry-only distribution. **template-dev is standing up the app repo** (consult expected).
|
||||
Rata's contributions shipped this session: the parity-matrix usage inventory (→ WT
|
||||
`docs/sdk/parity-matrix.md` `698cfc3`, behavioral-spec `c999b5f`, fixture corpus `3019ee6` = 66
|
||||
fixtures), the issue-#1 contract drift fix (`4bd9abd`), and the personal-WT endpoint for fixture
|
||||
capture. WT-side pipeline: behavioral-spec ✓ / parity-matrix ✓ / fixture-corpus ✓ → next is the
|
||||
**codegen spike (d)**. **Three SDK divergences pinned for our eventual repin:** D-1 (unknown SSE
|
||||
event → skip+diagnostics-hook, vs our current hard-raise in `_envelope_for_type`), D-2 (open-world
|
||||
enums), D-3 (typed eager `410 session_retired`). Full arc →
|
||||
`persistent-memory.d/2026-07-18-worldtree-sdk-371-and-sillytavern-app.md`.
|
||||
- **⚠️ OPEN Q for operator (priority):** how does this relate to the arbo-fork below? Different
|
||||
products (arbo = image-gen off ComfyUI; SillyTavern = chat off Worldtree), so no literal conflict
|
||||
— but is SillyTavern/SDK now the priority app, additive-to arbo, or does this session's
|
||||
don't-fork/sibling pattern change the arbo-fork plan? NOT resolved this session; preserved both.
|
||||
- **Awaiting operator:** explicit go on the fixture-capture run + which instance (demo vs personal)
|
||||
— worldtree-dev is holding on your call. Also awaiting template-dev's app-repo-standup consult.
|
||||
|
||||
**▶️ NEXT MAJOR: FORK ratatoskr for arbo image-gen (operator call 2026-07-17).** The arbo debug-observability
|
||||
idea did NOT become a feature bolted onto ratatoskr. Operator decision: **ratatoskr stays the Worldtree
|
||||
debug surface; the arbo image-gen product becomes a FORK of ratatoskr** (clean chat-first surface, debug
|
||||
panes hidden by default). The fork is the next major workstream; "get ready to assist with fork" is the
|
||||
standing directive.
|
||||
**▶️ NEXT MAJOR (operator call 2026-07-17, PRESERVED): FORK ratatoskr for arbo image-gen.** The
|
||||
arbo debug-observability idea did NOT become a feature bolted onto ratatoskr; ratatoskr stays the
|
||||
Worldtree debug surface, the **arbo image-gen product becomes a FORK of ratatoskr** (clean chat-first
|
||||
surface, debug panes hidden by default). "Get ready to assist with fork" is the standing directive.
|
||||
**arbo API intel** (comfy-dev 2026-07-17): validated-workflow-library REST API — `GET /workflows` →
|
||||
`POST /workflows/{id}/run` → 202 JobHandle → **poll** `GET /jobs/{id}` (NO SSE) → `outputs[].url`;
|
||||
Bearer via infra-ops `ENGINE_TOKEN`; deploy `irv-ml1:8201` WireGuard-only; canonical doc
|
||||
`vh/arbo:docs/rest-api.md` v1.4.27 + `/openapi.json`. (See the OPEN Q above re: arbo vs SDK/sibling.)
|
||||
|
||||
**✅ Pre-fork UI prep SHIPPED (v0.20.17, committed c678853, NOT pushed).** Web console: left+right debug
|
||||
panes (`#rail-left`, `#affect-console`) are now independently collapsible/hideable — chevron button folds
|
||||
each to a 22px re-open strip, `#center` reflows to fill, state persists per-pane in localStorage. Both
|
||||
collapsed = the clean chat surface the fork starts from. Playwright-verified. Web server bounced (now pid
|
||||
3194361 on :8765, serving the updated HTML). TUI untouched by this change (web-only).
|
||||
**✅ Pre-fork UI prep SHIPPED (v0.20.17, `c678853`, NOT pushed).** Web console left+right debug panes
|
||||
independently collapsible/hideable (chevron → 22px re-open strip, `#center` reflows, per-pane
|
||||
localStorage); both collapsed = the clean chat surface a fork starts from. Playwright-verified.
|
||||
|
||||
**⚠️ TUI DEPRECATED (operator call 2026-07-17) — rip pending, NOT a clean delete.** The textual TUI is
|
||||
superseded by the web interface; per no-backwards-compat it gets ripped. BLAST RADIUS (mapped, not yet
|
||||
executed): `tui.py` (textual app) + `tests/test_tui.py` delete cleanly. BUT `cli.py` is **SHARED, not
|
||||
TUI-only** — `web/entrypoint.py` and `tier3.py` both import `USER_AGENT` from it, and `cli.py` holds
|
||||
`ParsedArgs`/`_format_duration_ms`/`_format_usage` (used by tui) plus its own headless `CliPresenterState`.
|
||||
So the rip is a surgical disentangle, not `rm tui.py`. OPEN SCOPE Q for operator: remove textual-only
|
||||
(`tui.py`, keep `cli.py`'s headless CLI + `ratatoskr` entry) vs remove the whole terminal interface
|
||||
(relocate shared consts out of `cli.py` first). Breaking public-surface removal → **minor bump (needs
|
||||
operator approval)**. `textual`/`textual-dev` deps removable only after confirming tui.py is the sole user.
|
||||
**⚠️ TUI DEPRECATED (operator 2026-07-17) — rip pending, surgical not a clean delete.** `tui.py` +
|
||||
`tests/test_tui.py` delete cleanly, BUT `cli.py` is SHARED (`web/entrypoint.py` + `tier3.py` import
|
||||
`USER_AGENT`; `cli.py` holds `ParsedArgs`/`_format_duration_ms`/`_format_usage`). OPEN SCOPE Q: remove
|
||||
textual-only (`tui.py`) vs the whole terminal interface (relocate shared consts out of `cli.py`
|
||||
first). Breaking public-surface removal → minor bump (operator approval).
|
||||
|
||||
**arbo API intel (from comfy-dev 2026-07-17, banked for fork planning):** validated-workflow-library REST
|
||||
API, NOT raw txt2img. `GET /workflows` (~200 recipes: t2i/img2img/inpaint/video/…) → `POST /workflows/{id}/run`
|
||||
→ 202 JobHandle → **poll** `GET /jobs/{id}` (NO SSE/websocket — coarser than WT's live stream) → `GET
|
||||
outputs[].url` for the image. Thin RunRequest (prompt raw|compiled + optional seed/dims/image). Bearer
|
||||
auth via infra-ops `ENGINE_TOKEN`. Deploy: `irv-ml1:8201`, WireGuard-only. Canonical doc (pinnable):
|
||||
`vh/arbo:docs/rest-api.md` v1.4.27 + auto-served `/openapi.json`. comfy-dev offered a concrete t2i
|
||||
walkthrough + will coordinate the token when we smoke.
|
||||
**✅ #368 (user,character) memory silo test — DONE, PASSED live (WT b127).** The reason for the
|
||||
pre-session clear; closed. Write+read isolation proven end-to-end (conjunctive `{end_user,
|
||||
agent_self}`; cold-recall gave zero cross-character bleed); throwaway `ratatoskr:betty` deleted;
|
||||
Sindra intact; stores scrubbed. **Still QUEUED:** the backfill live-verify (synthetic legacy corpus
|
||||
— exercises machinery a born-fresh store skips). Full record →
|
||||
`persistent-memory.d/2026-07-18-368-silo-test-passed.md`. Sibling issues WT-owned: **#369**
|
||||
(recited-content re-promotion loop), **#367** (copula-absence bridge phrasing).
|
||||
|
||||
**#368 cross-agent Tier-3 bleed — ARC DONE from ratatoskr's side** (diagnosis → two-channel investigation →
|
||||
both scrubs → marker repro → enforcement read → silo test). Full forensic history moved to
|
||||
`persistent-memory.d/2026-07-18-368-silo-test-passed.md`. Net: WT b127 silos Tier-3 memory per (user,character)
|
||||
via conjunctive `{end_user, agent_self}` write+read; silo test PASSED live (see the ✅ summary above); our stores
|
||||
scrubbed clean afterward. tier3 CLI define/patch adapted to the b127 `role` schema (`860e0d5`). Sibling issues
|
||||
WT-owned: **#369** (recited-content re-promotion feedback loop), **#367** (copula-absence bridge phrasing).
|
||||
**Deferred/queued (all NON-URGENT):** (1) P06-driver **referential-frame A/B/C probe**
|
||||
(operator-ratified, waits on WT b122 → `persistent-memory.d/2026-07-17-referential-frame-probe.md`);
|
||||
(2) R39 Phase-2 **matched-quartets rebuild** (confirmatory, "whenever"); (3) bifrost **snapshot-cursor
|
||||
adoption** (ruled normative, not blocking → `persistent-memory.d/2026-07-16-bifrost-cursor-conformance.md`).
|
||||
|
||||
**✅ Cross-session name-recall arc COMPLETE + SHIPPED (v0.20.11→v0.20.15, pushed).** person-prime `scan`
|
||||
verb + `mark_superseded` verb both shipped, deployed to :8392, and live-verified; **WT #364 closed
|
||||
end-to-end both sides; Sindra durably recalls Vuong's name** (the "name unknown" negatives are RETIRED
|
||||
via mark_superseded, not just recency-evicted). Full arcs:
|
||||
`persistent-memory.d/2026-07-16-person-prime-scan-shipped.md` + `…-2026-07-16-wt364-r39-name-recall.md`.
|
||||
|
||||
**✅ Web-console UI shipped (v0.20.16, pushed):** code-block word-wrap + per-code-block & per-turn copy
|
||||
buttons (hover-revealed; one delegated `#tw` handler + LAN-http clipboard fallback; Playwright-verified).
|
||||
Served from disk → browser refresh picks it up, no :8765 restart for UI edits.
|
||||
|
||||
**OBSOLETE — Sindra pristine baseline WIPED 2026-07-18.** The whole Tier-3 memory.db was scrubbed to 0
|
||||
chunks (operator full-scrub ruling for #368 — contamination noise, nothing worth keeping; no backup taken
|
||||
per direct order). The old `sindra-baseline/*.db` checkpoints predate the scrub and no longer reflect a
|
||||
"clean 5-fact" target — the store is now born-empty. Any future test drive starts from the born-fresh store.
|
||||
|
||||
**Deferred/queued tasks (all NON-URGENT — tracked in Recent decisions):** (1) P06-driver **referential-
|
||||
frame A/B/C probe** (operator-ratified; waits on WT b122; read-shape + brokkr's scoring rubric captured →
|
||||
`persistent-memory.d/2026-07-17-referential-frame-probe.md`); (2) R39 Phase-2 **matched-quartets rebuild**
|
||||
(confirmatory, "whenever"); (3) bifrost **snapshot-cursor adoption** (ruled normative, not blocking →
|
||||
`persistent-memory.d/2026-07-16-bifrost-cursor-conformance.md`).
|
||||
|
||||
**Substrate / environment:** branch `main` at **v0.21.1** — local commits ahead of origin's v0.20.16 (`5a1883a`): tier3 b127-role adaptation (`860e0d5`) + memory snapshots, UNPUSHED; origin
|
||||
`git@gitea.phasefinal.com:vh/ratatoskr.git`. bifrost **`==1.1.4`** / wire v0.7 (maintenance-verb hasattr
|
||||
backstop + scan/cursor conformance harness); Worldtree openapi vendored 2.3.0; **suite 644 green**.
|
||||
Personal WT on **b127** (#368 (user,character) silo live + deployed both instances; #364 promotion-hygiene also live). The combined **:8392** provider (memory+affect) +
|
||||
**:8765** web are THE surfaces, dev-box BACKGROUND SHELLS — restart via
|
||||
`scratchpad/relaunch_by_pid.py <pid>` (env-preserving, self-daemonizing; pid via `ss -ltnp | grep <port>`);
|
||||
web serves static `index.html` from disk. `env.sh` sets the REQUIRED `RATATOSKR_MEMORY_EMBEDDING_DIM=1024`.
|
||||
Keys env-only mode-600 in `~/.config/ratatoskr/provider.env` + `RATATOSKR_ADMIN_API_KEY` (7 read scopes,
|
||||
**Substrate / environment:** branch `main` at **v0.21.1**; local commits ahead of origin's v0.20.16
|
||||
— incl. tier3 b127-role adaptation (`860e0d5`), #368 memory snapshots + silo work, and this session's
|
||||
contract-drift fix (`4bd9abd`) — **UNPUSHED**; origin `git@gitea.phasefinal.com:vh/ratatoskr.git`.
|
||||
bifrost **`==1.1.4`** / wire v0.7; WT openapi vendored 2.3.0; **suite 644 green**. Personal WT on
|
||||
**b127** (`http://10.250.50.152:8081`; #368 silo + #364 promotion-hygiene live both instances). The
|
||||
combined **:8392** provider (memory+affect) + **:8765** web are THE surfaces, dev-box BACKGROUND
|
||||
SHELLS — restart via `scratchpad/relaunch_by_pid.py <pid>` (env-preserving; pid via
|
||||
`ss -ltnp | grep <port>`). `env.sh` sets the REQUIRED `RATATOSKR_MEMORY_EMBEDDING_DIM=1024`. Keys
|
||||
env-only mode-600 in `~/.config/ratatoskr/provider.env` + `RATATOSKR_ADMIN_API_KEY` (7 read scopes,
|
||||
personal-:8081-only; Heimdall keys per-instance). **FOOT-GUN: check owner-scoped agents via
|
||||
`GET /agents/<owner>:<name>` with the OWNER key (`WORLDTREE_API_KEY`), NOT the admin key** — the admin
|
||||
token gives a false 404. `graphify-out/` runs dirty (auto-regen, never stage). v1 = full Worldtree I/O
|
||||
coverage, cuts when WT tags 1.0 (`docs/coverage-map.md`).
|
||||
`GET /agents/<owner>:<name>` with the OWNER key (`WORLDTREE_API_KEY`), NOT the admin key** — admin
|
||||
gives a false 404. `graphify-out/` runs dirty (auto-regen on the commit hook, never stage). v1 = full
|
||||
Worldtree I/O coverage, cuts when WT tags 1.0 (`docs/coverage-map.md`).
|
||||
|
||||
**Other live threads:** soong-lab = Tier-3 agent-authoring studio (v0.3.24 fixed the motivational
|
||||
string→object export; our workaround droppable for v0.3.24+ bundles). Open/deferred: #10 subject-
|
||||
migration watch; relational-dynamics-arc verify (bind via `--bifrost-url :8392`); P06 optimization-phase
|
||||
re-drive (brokkr brings prereg); we-framing-conditional affect-egress re-vendor. WT #356 resume-durability
|
||||
+ WT #367 (copula-absence bridge phrasing) = worldtree-owned.
|
||||
**Other live threads:** soong-lab = Tier-3 agent-authoring studio (v0.3.24+; motivational
|
||||
string→object export fixed upstream, our workaround droppable). Cross-session name-recall arc
|
||||
COMPLETE + shipped (v0.20.11→.16; WT #364 closed both sides; Sindra durably recalls Vuong via
|
||||
`mark_superseded` retirement, not recency-eviction). Sindra pristine baseline **WIPED 2026-07-18**
|
||||
(full #368 scrub, born-empty store — old `sindra-baseline/*.db` predate it). Open/deferred: #10
|
||||
subject-migration watch; relational-dynamics verify (bind `--bifrost-url :8392`); WT #356
|
||||
resume-durability = WT-owned.
|
||||
|
||||
## 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-06-15]` **Affect plane shipped (v0.17.2) + LIVE-PROVEN end-to-end against real Worldtree v0.35.2** → `persistent-memory.d/2026-06-15-affect-plane-shipped-v0-17-2-live-proven-end.md`
|
||||
- `[2026-06-16]` **#295 cold-recall miss root-caused — UPSTREAM, scope-axis asymmetry** → `persistent-memory.d/2026-06-16-295-cold-recall-miss-root-caused-upstream-sco.md`
|
||||
- `[2026-06-16]` **agent_self → make it CANONICAL (operator decided A)** → `persistent-memory.d/2026-06-16-agentself-make-it-canonical-operator-decided.md`
|
||||
- `[2026-06-16]` **Self-drive auth identity: bound session-create uses the CONSUMER Heimdall key as bearer, NOT `WORLDTREE_API_KEY`** → `persistent-memory.d/2026-06-16-self-drive-auth-identity-bound-session-create.md`
|
||||
- `[2026-06-16]` **Issue #17 v1 scope locked (operator 1A/2A): single-plane bind + dispatch-layer op-feed** → `persistent-memory.d/2026-06-16-issue-17-v1-scope-locked-operator-1a-2a-singl.md`
|
||||
- `[2026-06-16]` **agent_self lattice SHIPPED both sides → our axis-validation gap CLOSED (v0.17.5)** → `persistent-memory.d/2026-06-16-agentself-lattice-shipped-both-sides-our-axis.md`
|
||||
- `[2026-06-16]` **Repinned bifrost 0.7.0→0.8.0 + reimplemented memory `search` to the v0.6 scope split (operator-directed)** → `persistent-memory.d/2026-06-16-repinned-bifrost-0-7-0-0-8-0-reimplemented-me.md`
|
||||
- `[2026-06-17]` **Worldtree spec pin bumped v0.29.0→v0.35.16 (`562001a`→`f1b59f8`); cold recall closed on the WIRE** → `persistent-memory.d/2026-06-17-worldtree-spec-pin-bumped-v0-29-0-v0-35-16-56.md`
|
||||
- `[2026-06-17]` **End-to-end cold-recall proof RAN — our stack proven, #296 isolated** → `persistent-memory.d/2026-06-17-end-to-end-cold-recall-proof-ran-our-stack-pr.md`
|
||||
- `[2026-06-17]` **DELETE+redefine `ratatoskr:sindra` (operator-authorized; pre-v1 debug surface)** → `persistent-memory.d/2026-06-17-delete-redefine-ratatoskr-sindra-operator-aut.md`
|
||||
- `[2026-06-17]` **Promotion = 4-trigger hybrid (worldtree-dev, code-grounded):** → `persistent-memory.d/2026-06-17-promotion-4-trigger-hybrid-worldtree-dev-code.md`
|
||||
- `[2026-06-17]` **#296 triage sent to worldtree-dev** (`01KVBBH0…`): extraction SUBJECT-INVERSION (promotes assistant prose, drops the user's fact) + META-DESCRIPTION-not-content; verbose-persona aggravator. WAD-vs-bug resolved to BUG (extraction quality), not idle-gating.
|
||||
- `[2026-06-18]` **Tier-3 memory PROVEN end-to-end live** — `ratatoskr:terse-probe` recalled a seeded user fact in a COLD history-free session (scope_any → 1 hit @ cosine 0.6994). Closes the opening "how far from Tier-3 memory" question for normal agents.
|
||||
- `[2026-06-18]` **#296 Stages 1+2 closed** → `persistent-memory.d/2026-06-18-296-stages-1-2-closed.md`
|
||||
- `[2026-06-18]` **#17 implemented end-to-end via direct in-session TDD** → `persistent-memory.d/2026-06-18-17-implemented-end-to-end-via-direct-in-sessi.md`
|
||||
- `[2026-06-18]` **#17 live-smoke PROVEN — the whole thesis validated** → `persistent-memory.d/2026-06-18-17-live-smoke-proven-the-whole-thesis-validat.md`
|
||||
- `[2026-06-18]` **Fixed a pre-existing test-isolation bug exposed by the #17 CLI tests** → `persistent-memory.d/2026-06-18-fixed-a-pre-existing-test-isolation-bug-expos.md`
|
||||
- `[2026-06-18]` **#18 filed (composite endpoint + PAD read-endpoint) — DEFERRED, tracked at Gitea #18** → `persistent-memory.d/2026-06-18-18-filed-composite-endpoint-pad-read-endpoint.md`
|
||||
- `[2026-06-18]` **#18 SPLIT; Deliverable 1 (composite) routed to bifrost — Option C (operator)** → `persistent-memory.d/2026-06-18-18-split-deliverable-1-composite-routed-to-bi.md`
|
||||
- `[2026-06-18]` **FR-1 RESOLVED — the composite premise was unverified, now wire-proven: single-endpoint, caps-routed** → `persistent-memory.d/2026-06-18-fr-1-resolved-the-composite-premise-was-unver.md`
|
||||
- `[2026-06-18]` **#18 D2 implemented via direct in-session TDD (suite 470→482)** → `persistent-memory.d/2026-06-18-18-d2-implemented-via-direct-in-session-tdd-s.md`
|
||||
- `[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`
|
||||
@@ -276,7 +247,10 @@ decision. Captures rationale that won't be obvious from code alone.
|
||||
|
||||
- `[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`
|
||||
|
||||
_46 older entries (2026-05-* debug-TUI/web era + the 2026-06-14→16 Bifrost-provider build era) archived to archival-memory.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-style app is a fresh TS SIBLING, NOT a fork of Rata.** TS package ships first (Rata's repin rides the later Python milestone); internal-registry-only; template-dev stands up the app repo. → `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.**
|
||||
|
||||
_65 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._
|
||||
|
||||
@@ -286,25 +260,9 @@ Log of approaches that were tried and rejected, with rationale. Future-self
|
||||
defense against re-attempting the same cul-de-sac.
|
||||
|
||||
- `[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]` **"Sindra hasn't been registered" was an under-verified inference — WRONG** → `persistent-memory.d/2026-06-15-sindra-hasn-t-been-registered-was-an-under-ve.md`
|
||||
- `[2026-06-14]` **Artifact-only contract review can't validate against a dependency's ACTUAL behavior** → `persistent-memory.d/2026-06-14-artifact-only-contract-review-can-t-validate.md`
|
||||
- `[2026-06-15]` **"byte-equal" round-trip slip propagated affect→memory via copy-paste** → `persistent-memory.d/2026-06-15-byte-equal-round-trip-slip-propagated-affect.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]` **Memory plane TDD'd + shipped** → `persistent-memory.d/2026-06-15-memory-plane-tdd-d-shipped.md`
|
||||
- `[2026-06-15]` **Memory provider LIVE-PROVEN against personal v0.35.3; recall-injection is upstream** → `persistent-memory.d/2026-06-15-memory-provider-live-proven-against-personal.md`
|
||||
- `[2026-06-15]` **Diagnostic: our recall-search is SOUND — the cross-session recall gap is UPSTREAM, and it caught an upstream bug** → `persistent-memory.d/2026-06-15-diagnostic-our-recall-search-is-sound-the-cro.md`
|
||||
- `[2026-06-15]` **"Wire 200 ≠ recall works" — prove recall efficacy at the model's answer in a COLD (history-free) session, not on the wire** → `persistent-memory.d/2026-06-15-wire-200-recall-works-prove-recall-efficacy-a.md`
|
||||
- `[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-16]` **My #295 coupling hypothesis (the promoted question crowds out the fact at small top_k) was REFUTED** → `persistent-memory.d/2026-06-16-my-295-coupling-hypothesis-the-promoted-quest.md`
|
||||
- `[2026-06-16]` **#17 contract drifted from its own design in two spots, caught only by `/heid-contract-review` (not same-author paraphrase):** → `persistent-memory.d/2026-06-16-17-contract-drifted-from-its-own-design-in-tw.md`
|
||||
- `[2026-06-16]` **"No promotion" was checked TOO EARLY — Tier-3 promotion is ASYNC (lands AFTER the SSE turn-end)** → `persistent-memory.d/2026-06-16-no-promotion-was-checked-too-early-tier-3-pro.md`
|
||||
- `[2026-06-17]` **"sindra is GONE" (infra-ops, from `GET /agents` + admin token) was a FALSE NEGATIVE** → `persistent-memory.d/2026-06-17-sindra-is-gone-infra-ops-from-get-agents-admi.md`
|
||||
- `[2026-06-17]` **"Promotion didn't fire → #296" was PREMATURE — twice over** → `persistent-memory.d/2026-06-17-promotion-didn-t-fire-296-was-premature-twice.md`
|
||||
- `[2026-06-18]` **Wiping our `:8391` store does NOT reset Worldtree's promotion-side dedup** → `persistent-memory.d/2026-06-18-wiping-our-8391-store-does-not-reset-worldtre.md`
|
||||
- `[2026-06-18]` **`affect.emit` is POST-TURN ASYNC — checking the op-feed immediately after a turn MISSES it** → `persistent-memory.d/2026-06-18-affect-emit-is-post-turn-async-checking-the-o.md`
|
||||
- `[2026-06-18]` **Rationalized away a KNOWN contract-invariant deviation during TDD — only the cross-model code-review caught it** → `persistent-memory.d/2026-06-18-rationalized-away-a-known-contract-invariant.md`
|
||||
- `[2026-06-18]` **Latent SQLite thread-safety bug in the affect store, surfaced ONLY by the new HTTP read route** → `persistent-memory.d/2026-06-18-latent-sqlite-thread-safety-bug-in-the-affect.md`
|
||||
|
||||
- `[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`
|
||||
@@ -336,4 +294,4 @@ defense against re-attempting the same cul-de-sac.
|
||||
|
||||
- `[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`
|
||||
|
||||
_18 older entries (2026-05-* — the original debug-TUI/web build era) archived to archival-memory.md._
|
||||
_34 older entries (2026-05-* debug-TUI/web era + the 2026-06-14 → 06-18 foot-gun cluster) archived to archival-memory.md._
|
||||
|
||||
Reference in New Issue
Block a user