From 84d8c3f65fb9ad30a1ba1d3ad2b426c2bcdd3269 Mon Sep 17 00:00:00 2001 From: Vuong Hoang Date: Wed, 17 Jun 2026 11:15:06 -0700 Subject: [PATCH] =?UTF-8?q?memory:=20snapshot=20=E2=80=94=20cold-recall=20?= =?UTF-8?q?arc=20PROVEN=20live=20e2e=20(#297/#298=20union=20recall;=20WT?= =?UTF-8?q?=20v0.35.16=20emits=20scope=5Fany=20into=20our=20v0.17.6=20stor?= =?UTF-8?q?e);=20#296=20extraction=20quality=20the=20isolated=20upstream?= =?UTF-8?q?=20gap=20(triage=E2=86=92worldtree-dev,=20both=20symptoms=20loc?= =?UTF-8?q?alized=20in-code:=20empty=20=5FEXTRACTOR=5FSYSTEM=20+=20both-ro?= =?UTF-8?q?les=20prefilter);=20sindra=20restored=20(DELETE+redefine,=20rol?= =?UTF-8?q?e:character=E2=86=92mistral-small-4,=20memory:{});=20learnings:?= =?UTF-8?q?=20Tier-3=20owner-scoped,=20define-takes-role,=20promotion=204-?= =?UTF-8?q?trigger=20hybrid,=20DELETE=E2=89=A0drain?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- persistent-memory.md | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/persistent-memory.md b/persistent-memory.md index d647144..c77f299 100644 --- a/persistent-memory.md +++ b/persistent-memory.md @@ -41,22 +41,22 @@ model output is untrusted); upstream API key stays server-side (INV-003). ## Current state / in-flight -_As of 2026-06-16:_ +_As of 2026-06-17:_ -**LATEST (2026-06-17) — COLD RECALL CLOSED END-TO-END + WORLDTREE SPEC REPINNED.** -Worldtree shipped its half: v0.35.16 adopts the bifrost v0.6 wire and emits -`scope_any`/`scope_all` on recall (#297 client-side per-scope-value union recall + -#298/#299 bifrost-v0.6 adoption). With our v0.17.6 provider, cold cross-session recall -is now CLOSED end-to-end. **Remaining: a live re-smoke against a personal instance on -v0.35.16** (the running smoke target was v0.35.2/.3 — needs infra-ops to update it). -Worldtree spec pin bumped `562001a`/v0.29.0 → `f1b59f8`/v0.35.16 (`docs/SPEC-PIN.md` + -`worldtree-spec-rev`; 285-commit catch-up). Client-facing deltas reviewed, NONE break -our consumer: #211 agent-slug rename (saga→echo, actor→mask — slugs only), #245 -`end_user_id` persistence + memory-scope resolver, #187/#188/#219 Tier-3 define/PATCH -policy (additive); the `bifrost` binding field + `ephemeral_does_not_accept_bifrost` 422 -are now in-tree (the #17 surface). No ratatoskr code change for the spec bump; shipped -as a `pin:` commit (no package bump — docs/pin only). The provider half shipped earlier -as v0.17.6 (`96d61a4`, tag v0.17.6). +**LATEST (2026-06-17 PM) — END-TO-END COLD-RECALL PROOF RAN; OUR STACK PROVEN, #296 IS +THE ISOLATED GAP.** Drove the full bound proof against personal WT v0.35.16 with the +restored `ratatoskr:sindra`. **Every leg of OUR stack is proven:** (1) #297/#298 union +recall is LIVE — WT dispatched `scope_any=[{end_user:sindra-proof},{agent_self:ratatoskr:sindra}]` +into our v0.17.6 store; (2) write path — promotion fired ~4min post-seed, `upsert_many` +dispatched, chunks persisted; (3) read path — a COLD (history-free) session's recall +returned the chunks via `scope_any` (2 hits). **The one failure is UPSTREAM #296 extraction +quality:** promotion stored third-person summaries of sindra's PERSONA output ("Assistant's +flirtatious response…") and DROPPED the user's stated fact ("dark chocolate with sea salt") +— so cold recall returned useless chunks and sindra (deflecting persona) didn't recall it. +Triage sent to worldtree-dev (msg `01KVBBH0QRGT34GDJQEX5ACTT1`, thread `01KVB4WM…`); **waiting +on their #296 response** (althing monitor armed). 2 garbage chunks (scope `{end_user:sindra-proof}`) +sit in `memory.db` — disposable. Worldtree spec pin is now `f1b59f8`/v0.35.16 (`4eee7c8`); +provider half is v0.17.6 (`96d61a4`). Nothing blocked on us — it's worldtree-dev's #296 court. **(2026-06-16 PM) — BIFROST REPINNED 0.7.0→0.8.0 (wire v0.5→v0.6).** The memory `search` scope filter was split into `scope_all` (AND/intersection) + @@ -227,6 +227,11 @@ decision. Captures rationale that won't be obvious from code alone. - `[2026-06-17]` **Worldtree spec pin bumped v0.29.0→v0.35.16 (`562001a`→`f1b59f8`); cold recall CLOSED end-to-end.** Worldtree shipped #297 (client-side per-scope-value union recall) + #298/#299 (adopt the bifrost v0.6 `scope_any`/`scope_all` wire) — it now emits `scope_any` on recall, the upstream half that pairs with our v0.17.6 provider. Re-vendored `conversation-api-spec.md` + `conversation_api.contract.md`; diff-reviewed the 285-commit catch-up — no client-breaking changes (#211 agent-slug rename saga→echo/actor→mask is slugs-only; #245 end_user_id+memory-scope; #187/#188/#219 Tier-3 define/PATCH additive; error codes stable). Shipped as a `pin:` commit, NO package bump (docs/pin-only, no ratatoskr code; per SemVer SKIP for docs-only). **Remaining proof: a live cold-recall re-smoke against a personal instance on v0.35.16** — the smoke target ran v0.35.2/.3, needs infra-ops to update it. +- `[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 (WT emits `scope_any`), write path (promote→upsert→persist), and cold read (scope_any returns hits) ALL proven. Lone gap = upstream #296 extraction quality. Refines the spec-repin entry's "cold recall closes end-to-end": the WIRE closed; actual fact-recall is #296-blocked. (triage `01KVBBH0…`) +- `[2026-06-17]` **DELETE+redefine `ratatoskr:sindra` (operator-authorized; pre-v1 debug surface).** She SURVIVED the rebuild but was STALE (dead model `artemis-31b-v1i` + no memory block from Phase-2.0 tooling); 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`). Reasoning bind needs a `character`-role bind reorder (worldtree-dev flagged to operator). Our `tier3.py` define is Phase-2.0-stale (no role/memory/persona layers) — untracked modernization follow-up. +- `[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. The seed promoted at ~4min (per-turn salience/turn-scan, before the idle floor). +- `[2026-06-17]` **#296 triage sent to worldtree-dev** (`01KVBBH0QRGT34GDJQEX5ACTT1`): extraction SUBJECT-INVERSION (promotes assistant prose, drops the user's fact) + META-DESCRIPTION-not-content; verbose-persona aggravator. The WAD-vs-bug cut resolved to BUG (extraction quality), not idle-gating. + _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 @@ -266,3 +271,5 @@ defense against re-attempting the same cul-de-sac. - `[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` (`injector.py:203`/`_store_helpers.py:101`), so the question can't crowd the fact out at search level. Reasonable cross-frontier hypothesis, correctly framed as a hypothesis not a conclusion; the real cause was the scope-axis asymmetry. Lesson: offer provider-side hypotheses, let the upstream owner check them against their code. - `[2026-06-16]` **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` that INV-005 promised; the `session_id` comment said "None for search/get/delete" contradicting the dispatch-layer design (the JWT carries session_id for all verbs at dispatch). Cross-model paraphrase is load-bearing for catching an author's own contract-vs-intent drift. - `[2026-06-16]` **"No promotion" was checked TOO EARLY — Tier-3 promotion is ASYNC (lands AFTER the SSE turn-end).** The cold-recall probe's immediate post-turn fixture check showed 3 chunks (no promotion); a later check (during the v0.17.5 provider restart) found 5 — the probe HAD promoted 2 chunks (its question `acc3d49` + the model's non-answer `4773704`), just late. Don't trust an immediate post-turn fixture snapshot to judge promotion; it lands after the turn completes. (Same family as the "wire-200 ≠ recall, prove it in a cold session" lesson, extended to promotion timing — and the reason #17's contract pins a post-turn grace window + fixture before/after assertion.) +- `[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 whether a Tier-3 agent exists, `GET /agents/:` with the OWNER key. (Extends the 2026-06-15 "Sindra registration under-verified" lesson — even the roster query can't see consumer agents; only the owner-scoped point-GET does.) +- `[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 (assistant-prose promoted, user-fact dropped), not non-firing. "No upsert while a session is live and `<10min` idle" is WAD, not a miss. (Extends the 2026-06-16 "checked too early" entry with the multi-trigger timing + the fired-but-bad-content distinction.)