diff --git a/persistent-memory.d/2026-06-14-artifact-only-contract-review-can-t-validate.md b/persistent-memory.d/2026-06-14-artifact-only-contract-review-can-t-validate.md new file mode 100644 index 0000000..74134a3 --- /dev/null +++ b/persistent-memory.d/2026-06-14-artifact-only-contract-review-can-t-validate.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-15-affect-plane-shipped-v0-17-2-live-proven-end.md b/persistent-memory.d/2026-06-15-affect-plane-shipped-v0-17-2-live-proven-end.md new file mode 100644 index 0000000..301f038 --- /dev/null +++ b/persistent-memory.d/2026-06-15-affect-plane-shipped-v0-17-2-live-proven-end.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-15-byte-equal-round-trip-slip-propagated-affect.md b/persistent-memory.d/2026-06-15-byte-equal-round-trip-slip-propagated-affect.md new file mode 100644 index 0000000..b3853d7 --- /dev/null +++ b/persistent-memory.d/2026-06-15-byte-equal-round-trip-slip-propagated-affect.md @@ -0,0 +1 @@ +`[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) diff --git a/persistent-memory.d/2026-06-15-diagnostic-our-recall-search-is-sound-the-cro.md b/persistent-memory.d/2026-06-15-diagnostic-our-recall-search-is-sound-the-cro.md new file mode 100644 index 0000000..840d7d0 --- /dev/null +++ b/persistent-memory.d/2026-06-15-diagnostic-our-recall-search-is-sound-the-cro.md @@ -0,0 +1 @@ +`[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.** diff --git a/persistent-memory.d/2026-06-15-memory-plane-tdd-d-shipped.md b/persistent-memory.d/2026-06-15-memory-plane-tdd-d-shipped.md new file mode 100644 index 0000000..9345e3d --- /dev/null +++ b/persistent-memory.d/2026-06-15-memory-plane-tdd-d-shipped.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-15-memory-provider-live-proven-against-personal.md b/persistent-memory.d/2026-06-15-memory-provider-live-proven-against-personal.md new file mode 100644 index 0000000..a01557e --- /dev/null +++ b/persistent-memory.d/2026-06-15-memory-provider-live-proven-against-personal.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-15-sindra-hasn-t-been-registered-was-an-under-ve.md b/persistent-memory.d/2026-06-15-sindra-hasn-t-been-registered-was-an-under-ve.md new file mode 100644 index 0000000..88ad160 --- /dev/null +++ b/persistent-memory.d/2026-06-15-sindra-hasn-t-been-registered-was-an-under-ve.md @@ -0,0 +1 @@ +`[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/:` with the owner key does.) diff --git a/persistent-memory.d/2026-06-15-wire-200-recall-works-prove-recall-efficacy-a.md b/persistent-memory.d/2026-06-15-wire-200-recall-works-prove-recall-efficacy-a.md new file mode 100644 index 0000000..596f181 --- /dev/null +++ b/persistent-memory.d/2026-06-15-wire-200-recall-works-prove-recall-efficacy-a.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-16-17-contract-drifted-from-its-own-design-in-tw.md b/persistent-memory.d/2026-06-16-17-contract-drifted-from-its-own-design-in-tw.md new file mode 100644 index 0000000..9e0b27a --- /dev/null +++ b/persistent-memory.d/2026-06-16-17-contract-drifted-from-its-own-design-in-tw.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-16-295-cold-recall-miss-root-caused-upstream-sco.md b/persistent-memory.d/2026-06-16-295-cold-recall-miss-root-caused-upstream-sco.md new file mode 100644 index 0000000..5db785a --- /dev/null +++ b/persistent-memory.d/2026-06-16-295-cold-recall-miss-root-caused-upstream-sco.md @@ -0,0 +1 @@ +`[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**. diff --git a/persistent-memory.d/2026-06-16-agentself-lattice-shipped-both-sides-our-axis.md b/persistent-memory.d/2026-06-16-agentself-lattice-shipped-both-sides-our-axis.md new file mode 100644 index 0000000..b6274af --- /dev/null +++ b/persistent-memory.d/2026-06-16-agentself-lattice-shipped-both-sides-our-axis.md @@ -0,0 +1 @@ +`[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). diff --git a/persistent-memory.d/2026-06-16-agentself-make-it-canonical-operator-decided.md b/persistent-memory.d/2026-06-16-agentself-make-it-canonical-operator-decided.md new file mode 100644 index 0000000..879bd16 --- /dev/null +++ b/persistent-memory.d/2026-06-16-agentself-make-it-canonical-operator-decided.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-16-issue-17-v1-scope-locked-operator-1a-2a-singl.md b/persistent-memory.d/2026-06-16-issue-17-v1-scope-locked-operator-1a-2a-singl.md new file mode 100644 index 0000000..ac0e5c3 --- /dev/null +++ b/persistent-memory.d/2026-06-16-issue-17-v1-scope-locked-operator-1a-2a-singl.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-16-my-295-coupling-hypothesis-the-promoted-quest.md b/persistent-memory.d/2026-06-16-my-295-coupling-hypothesis-the-promoted-quest.md new file mode 100644 index 0000000..c924c4e --- /dev/null +++ b/persistent-memory.d/2026-06-16-my-295-coupling-hypothesis-the-promoted-quest.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-16-no-promotion-was-checked-too-early-tier-3-pro.md b/persistent-memory.d/2026-06-16-no-promotion-was-checked-too-early-tier-3-pro.md new file mode 100644 index 0000000..152792a --- /dev/null +++ b/persistent-memory.d/2026-06-16-no-promotion-was-checked-too-early-tier-3-pro.md @@ -0,0 +1 @@ +`[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.) diff --git a/persistent-memory.d/2026-06-16-repinned-bifrost-0-7-0-0-8-0-reimplemented-me.md b/persistent-memory.d/2026-06-16-repinned-bifrost-0-7-0-0-8-0-reimplemented-me.md new file mode 100644 index 0000000..8ac8e8c --- /dev/null +++ b/persistent-memory.d/2026-06-16-repinned-bifrost-0-7-0-0-8-0-reimplemented-me.md @@ -0,0 +1 @@ +`[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.)** diff --git a/persistent-memory.d/2026-06-16-self-drive-auth-identity-bound-session-create.md b/persistent-memory.d/2026-06-16-self-drive-auth-identity-bound-session-create.md new file mode 100644 index 0000000..40daeaa --- /dev/null +++ b/persistent-memory.d/2026-06-16-self-drive-auth-identity-bound-session-create.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-17-delete-redefine-ratatoskr-sindra-operator-aut.md b/persistent-memory.d/2026-06-17-delete-redefine-ratatoskr-sindra-operator-aut.md new file mode 100644 index 0000000..4c7f2cf --- /dev/null +++ b/persistent-memory.d/2026-06-17-delete-redefine-ratatoskr-sindra-operator-aut.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-17-end-to-end-cold-recall-proof-ran-our-stack-pr.md b/persistent-memory.d/2026-06-17-end-to-end-cold-recall-proof-ran-our-stack-pr.md new file mode 100644 index 0000000..359cc60 --- /dev/null +++ b/persistent-memory.d/2026-06-17-end-to-end-cold-recall-proof-ran-our-stack-pr.md @@ -0,0 +1 @@ +`[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). diff --git a/persistent-memory.d/2026-06-17-promotion-4-trigger-hybrid-worldtree-dev-code.md b/persistent-memory.d/2026-06-17-promotion-4-trigger-hybrid-worldtree-dev-code.md new file mode 100644 index 0000000..c5035ef --- /dev/null +++ b/persistent-memory.d/2026-06-17-promotion-4-trigger-hybrid-worldtree-dev-code.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-17-promotion-didn-t-fire-296-was-premature-twice.md b/persistent-memory.d/2026-06-17-promotion-didn-t-fire-296-was-premature-twice.md new file mode 100644 index 0000000..ba3e760 --- /dev/null +++ b/persistent-memory.d/2026-06-17-promotion-didn-t-fire-296-was-premature-twice.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-17-sindra-is-gone-infra-ops-from-get-agents-admi.md b/persistent-memory.d/2026-06-17-sindra-is-gone-infra-ops-from-get-agents-admi.md new file mode 100644 index 0000000..9196cf4 --- /dev/null +++ b/persistent-memory.d/2026-06-17-sindra-is-gone-infra-ops-from-get-agents-admi.md @@ -0,0 +1 @@ +`[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/:` with the OWNER key. diff --git a/persistent-memory.d/2026-06-17-worldtree-spec-pin-bumped-v0-29-0-v0-35-16-56.md b/persistent-memory.d/2026-06-17-worldtree-spec-pin-bumped-v0-29-0-v0-35-16-56.md new file mode 100644 index 0000000..1918f9e --- /dev/null +++ b/persistent-memory.d/2026-06-17-worldtree-spec-pin-bumped-v0-29-0-v0-35-16-56.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-18-17-implemented-end-to-end-via-direct-in-sessi.md b/persistent-memory.d/2026-06-18-17-implemented-end-to-end-via-direct-in-sessi.md new file mode 100644 index 0000000..67aec4c --- /dev/null +++ b/persistent-memory.d/2026-06-18-17-implemented-end-to-end-via-direct-in-sessi.md @@ -0,0 +1 @@ +`[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`. diff --git a/persistent-memory.d/2026-06-18-17-live-smoke-proven-the-whole-thesis-validat.md b/persistent-memory.d/2026-06-18-17-live-smoke-proven-the-whole-thesis-validat.md new file mode 100644 index 0000000..c4014c4 --- /dev/null +++ b/persistent-memory.d/2026-06-18-17-live-smoke-proven-the-whole-thesis-validat.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-18-18-d2-implemented-via-direct-in-session-tdd-s.md b/persistent-memory.d/2026-06-18-18-d2-implemented-via-direct-in-session-tdd-s.md new file mode 100644 index 0000000..a55ea39 --- /dev/null +++ b/persistent-memory.d/2026-06-18-18-d2-implemented-via-direct-in-session-tdd-s.md @@ -0,0 +1 @@ +`[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). diff --git a/persistent-memory.d/2026-06-18-18-filed-composite-endpoint-pad-read-endpoint.md b/persistent-memory.d/2026-06-18-18-filed-composite-endpoint-pad-read-endpoint.md new file mode 100644 index 0000000..e692100 --- /dev/null +++ b/persistent-memory.d/2026-06-18-18-filed-composite-endpoint-pad-read-endpoint.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-18-18-split-deliverable-1-composite-routed-to-bi.md b/persistent-memory.d/2026-06-18-18-split-deliverable-1-composite-routed-to-bi.md new file mode 100644 index 0000000..5e905da --- /dev/null +++ b/persistent-memory.d/2026-06-18-18-split-deliverable-1-composite-routed-to-bi.md @@ -0,0 +1 @@ +`[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`] diff --git a/persistent-memory.d/2026-06-18-296-stages-1-2-closed.md b/persistent-memory.d/2026-06-18-296-stages-1-2-closed.md new file mode 100644 index 0000000..067b3c2 --- /dev/null +++ b/persistent-memory.d/2026-06-18-296-stages-1-2-closed.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-18-affect-emit-is-post-turn-async-checking-the-o.md b/persistent-memory.d/2026-06-18-affect-emit-is-post-turn-async-checking-the-o.md new file mode 100644 index 0000000..17e101a --- /dev/null +++ b/persistent-memory.d/2026-06-18-affect-emit-is-post-turn-async-checking-the-o.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-18-fixed-a-pre-existing-test-isolation-bug-expos.md b/persistent-memory.d/2026-06-18-fixed-a-pre-existing-test-isolation-bug-expos.md new file mode 100644 index 0000000..2c4c32a --- /dev/null +++ b/persistent-memory.d/2026-06-18-fixed-a-pre-existing-test-isolation-bug-expos.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-18-fr-1-resolved-the-composite-premise-was-unver.md b/persistent-memory.d/2026-06-18-fr-1-resolved-the-composite-premise-was-unver.md new file mode 100644 index 0000000..79d11d7 --- /dev/null +++ b/persistent-memory.d/2026-06-18-fr-1-resolved-the-composite-premise-was-unver.md @@ -0,0 +1 @@ +`[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. diff --git a/persistent-memory.d/2026-06-18-latent-sqlite-thread-safety-bug-in-the-affect.md b/persistent-memory.d/2026-06-18-latent-sqlite-thread-safety-bug-in-the-affect.md new file mode 100644 index 0000000..09d05ab --- /dev/null +++ b/persistent-memory.d/2026-06-18-latent-sqlite-thread-safety-bug-in-the-affect.md @@ -0,0 +1 @@ +`[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.** diff --git a/persistent-memory.d/2026-06-18-rationalized-away-a-known-contract-invariant.md b/persistent-memory.d/2026-06-18-rationalized-away-a-known-contract-invariant.md new file mode 100644 index 0000000..e88a938 --- /dev/null +++ b/persistent-memory.d/2026-06-18-rationalized-away-a-known-contract-invariant.md @@ -0,0 +1 @@ +`[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.** diff --git a/persistent-memory.d/2026-06-18-wiping-our-8391-store-does-not-reset-worldtre.md b/persistent-memory.d/2026-06-18-wiping-our-8391-store-does-not-reset-worldtre.md new file mode 100644 index 0000000..52ed091 --- /dev/null +++ b/persistent-memory.d/2026-06-18-wiping-our-8391-store-does-not-reset-worldtre.md @@ -0,0 +1 @@ +`[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.) diff --git a/persistent-memory.d/2026-06-19-18-d1-shipped-composite-buildcombinedapp-on-8.md b/persistent-memory.d/2026-06-19-18-d1-shipped-composite-buildcombinedapp-on-8.md new file mode 100644 index 0000000..4b62934 --- /dev/null +++ b/persistent-memory.d/2026-06-19-18-d1-shipped-composite-buildcombinedapp-on-8.md @@ -0,0 +1 @@ +`[2026-06-19]` **#18 D1 SHIPPED — composite `build_combined_app` on `:8392` (`v0.17.16`, `7f4ceaa`); #18 CLOSED; published `v0.18.0` (`359dbb1`).** `build_combined_provider_app` wraps bifrost's public builder over both stores + the shared read route; op-feed `plane='combined'` per-path. Direct in-session TDD; heid-code-review panel (Gróa/Hulda/Regin) returned ZERO drift. Live-proven at wire+dispatch; WT-turn gated on infra-ops `:8392` allowlist. diff --git a/persistent-memory.d/2026-06-19-18-d2-shipped-v0-17-14-39eebd1-and-the-full-1.md b/persistent-memory.d/2026-06-19-18-d2-shipped-v0-17-14-39eebd1-and-the-full-1.md new file mode 100644 index 0000000..5e85e03 --- /dev/null +++ b/persistent-memory.d/2026-06-19-18-d2-shipped-v0-17-14-39eebd1-and-the-full-1.md @@ -0,0 +1 @@ +`[2026-06-19]` **#18 D2 SHIPPED (`v0.17.14`, `39eebd1`) and the full #17+#18 arc PUSHED to origin.** Live-smoke PROVEN against real data (throwaway `:8393`/`:8766` vs the real `affect.db` → real sindra/vuong PAD through the full web→provider chain; Playwright DOM check confirmed the pane render + the F1 fix — no fabricated "neutral"). The push carried 9 previously-held commits incl. the deliberately-unpushed #17 (`v0.17.8`→`v0.17.13`); origin/main now == `39eebd1`, tag `v0.17.14`. diff --git a/persistent-memory.d/2026-06-19-bifrost-repinned-0-8-0-0-10-0-affect-fetch-be.md b/persistent-memory.d/2026-06-19-bifrost-repinned-0-8-0-0-10-0-affect-fetch-be.md new file mode 100644 index 0000000..41d98d4 --- /dev/null +++ b/persistent-memory.d/2026-06-19-bifrost-repinned-0-8-0-0-10-0-affect-fetch-be.md @@ -0,0 +1 @@ +`[2026-06-19]` **bifrost repinned 0.8.0→0.10.0; `affect.fetch` became MANDATORY (strong-or-absent).** 0.10.0's `_supports_affect_plane` requires `affect_supported`+`emit`+`fetch` and gates EVERY affect op — an emit-only store 400s. Implemented `affect.fetch` (`v0.17.15`, `ca6af6b`) conformed to bifrost's reference `InMemoryAffectStore.fetch` (`{found, snapshot?}`): the forced D1 prerequisite + a new Worldtree I/O point consumed. Flagged the now-stale consumer-guide line to bifrost-dev (fixed `a2e6d62`). diff --git a/persistent-memory.d/2026-06-19-full-wt-driven-8392-live-smoke-is-infra-gated.md b/persistent-memory.d/2026-06-19-full-wt-driven-8392-live-smoke-is-infra-gated.md new file mode 100644 index 0000000..5504aa7 --- /dev/null +++ b/persistent-memory.d/2026-06-19-full-wt-driven-8392-live-smoke-is-infra-gated.md @@ -0,0 +1 @@ +`[2026-06-19]` **Full WT-driven `:8392` live-smoke is infra-gated — `:8392` not in WT's `BIFROST_CLIENT_ALLOWED_HOSTS` (bind 422s).** New provider ports are NOT auto-allowlisted (only `:8390/:8391` are). Self-driven dispatch (minted consumer-key JWTs → `:8392`) is the wire-proof; the WT-turn needs infra-ops to add `:8392` (requested `01KVHWJGTT…`). diff --git a/persistent-memory.d/2026-06-19-heid-code-review-pulled-more-weight-than-its.md b/persistent-memory.d/2026-06-19-heid-code-review-pulled-more-weight-than-its.md new file mode 100644 index 0000000..2a71677 --- /dev/null +++ b/persistent-memory.d/2026-06-19-heid-code-review-pulled-more-weight-than-its.md @@ -0,0 +1 @@ +`[2026-06-19]` **heid-code-review pulled MORE weight than its own "marginal" self-assessment.** The panel returned zero drift, but its single test-fidelity finding CASCADED into 2 real latent-bug fixes when applied (the memory `check_same_thread` bug + Regin's op-feed field-name bug). **Lesson: a contract-fidelity nudge can transitively expose bugs the test never reached — don't dismiss a "marginal" finding by its count.** diff --git a/persistent-memory.d/2026-06-19-op-feed-handshake-field-name-fix-17-v0-17-17.md b/persistent-memory.d/2026-06-19-op-feed-handshake-field-name-fix-17-v0-17-17.md new file mode 100644 index 0000000..a1360e9 --- /dev/null +++ b/persistent-memory.d/2026-06-19-op-feed-handshake-field-name-fix-17-v0-17-17.md @@ -0,0 +1 @@ +`[2026-06-19]` **op-feed handshake field-name fix (#17, `v0.17.17` `d60b77d`): `capabilities_requested`→`capabilities`.** The summary read a field that never exists on the wire (bifrost reads `capabilities`, `_protocol.py:181`) → caps_requested was always null. Surfaced by the heid panel (Regin) during the D1 review — a latent #17 bug, not D1 drift. diff --git a/persistent-memory.d/2026-06-19-ratatoskr-is-a-reference-implementation-of-th.md b/persistent-memory.d/2026-06-19-ratatoskr-is-a-reference-implementation-of-th.md new file mode 100644 index 0000000..0cbc90e --- /dev/null +++ b/persistent-memory.d/2026-06-19-ratatoskr-is-a-reference-implementation-of-th.md @@ -0,0 +1 @@ +`[2026-06-19]` **Ratatoskr is a REFERENCE implementation of the Worldtree/Bifrost standard (operator).** Adopt the dep's canonical way (even if ours works); INFORM of drift/gaps; ADVISE a different approach only when ours is genuinely better (dep owner decides), never unilaterally fork. [auto-memory `feedback-ratatoskr-is-a-reference-impl-adopt-canonical`] diff --git a/persistent-memory.d/2026-06-19-ratatoskr-v1-is-derived-from-worldtree-i-o-co.md b/persistent-memory.d/2026-06-19-ratatoskr-v1-is-derived-from-worldtree-i-o-co.md new file mode 100644 index 0000000..8b7dac7 --- /dev/null +++ b/persistent-memory.d/2026-06-19-ratatoskr-v1-is-derived-from-worldtree-i-o-co.md @@ -0,0 +1 @@ +`[2026-06-19]` **Ratatoskr v1 is DERIVED from Worldtree I/O coverage (operator) — no self-defined feature ROADMAP.** v1 = consume all of Worldtree's I/O points, reached when Worldtree hits 1.0; the convergence target is a coverage map, not a 3–7 capability list. [auto-memory `project-ratatoskr-v1-derived-from-worldtree-io-coverage`] diff --git a/persistent-memory.d/2026-06-19-the-same-checksamethread-sqlite-bug-recurred.md b/persistent-memory.d/2026-06-19-the-same-checksamethread-sqlite-bug-recurred.md new file mode 100644 index 0000000..20c3629 --- /dev/null +++ b/persistent-memory.d/2026-06-19-the-same-checksamethread-sqlite-bug-recurred.md @@ -0,0 +1 @@ +`[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).** Heid's test-fidelity finding (the D1 dispatch test used `describe_store` where the contract says `search`) → fixing it to `search` tripped `sqlite3.ProgrammingError` because `open_memory_store` also lacked `check_same_thread=False`. Fixed (mirrors affect INV-006). **Lesson: this bug is PER-STORE — every sqlite-backed ASGI store needs `check_same_thread=False`; an HTTP-layer (TestClient) test exposes what direct-store tests can't, and the composite serving memory over HTTP makes it bite.** diff --git a/persistent-memory.d/2026-06-20-18-s-final-leg-proven-composite-8392-wt-drive.md b/persistent-memory.d/2026-06-20-18-s-final-leg-proven-composite-8392-wt-drive.md new file mode 100644 index 0000000..fbc4dff --- /dev/null +++ b/persistent-memory.d/2026-06-20-18-s-final-leg-proven-composite-8392-wt-drive.md @@ -0,0 +1 @@ +`[2026-06-20]` **#18's final leg PROVEN — composite `:8392` WT-driven smoke ran end-to-end + persisted.** infra-ops allowlisted `10.100.10.50:8392` on the personal WT (`01KVHWJGTT…`); a real WT turn (session `b83a66b6`, `ratatoskr:sindra`, fresh end_user `resmoke-choco-1`) dispatched the full both-plane lifecycle through ONE endpoint — handshake (both caps) → `affect.fetch` + `memory.search` → `affect.emit` (`stored:true`) → `memory.upsert_many` (`upserted:1`) — both writes verified in our SQLite (`affect_snapshots` PAD row + `memory_chunks` chunk `2df1b79…`). First attempt blocked by a `model_unavailable` outage on the personal WT (both agents' models down), operator-fixed mid-session, then clean. The composite has no open legs. diff --git a/persistent-memory.d/2026-06-20-sindra-has-real-pad-but-empty-memory-the-affe.md b/persistent-memory.d/2026-06-20-sindra-has-real-pad-but-empty-memory-the-affe.md new file mode 100644 index 0000000..bb1d869 --- /dev/null +++ b/persistent-memory.d/2026-06-20-sindra-has-real-pad-but-empty-memory-the-affe.md @@ -0,0 +1 @@ +`[2026-06-20]` **Sindra has real PAD but ~empty memory — the affect/memory persistence asymmetry, confirmed on real sessions.** affect EMITS every turn (persona always accumulates: vuong 8→14 interactions across the session); memory only writes on a PROMOTION trigger (salience / turn_count≥6 / idle-≥10min flush). Two real vuong sessions through the combined bind (`04d6414c`, `433541fe`) drove affect emits + memory SEARCHES but ZERO promotion upserts → `memory.db` holds only the smoke fixture, zero vuong chunks. Operator: acceptable (server-takedown = "Sindra bonked on the head"; transient memory loss WAD). Operational catch: combined-as-default web bind saves persona reliably but silently LOSES memory if a session closes before a promotion trigger fires. diff --git a/persistent-memory.d/2026-06-20-the-post-turn-async-timing-trap-bit-again-eve.md b/persistent-memory.d/2026-06-20-the-post-turn-async-timing-trap-bit-again-eve.md new file mode 100644 index 0000000..b72a1ca --- /dev/null +++ b/persistent-memory.d/2026-06-20-the-post-turn-async-timing-trap-bit-again-eve.md @@ -0,0 +1 @@ +`[2026-06-20]` **The post-turn-async timing trap bit AGAIN — even a 35s post-`[done]` read missed the promotion `upsert_many` by ~2s** (it landed `19:48:58`; the read was ~`19:48:56`). A 15s-interval background poll caught it on the first tick. Same family as the affect.emit / async-promotion traps already logged — re-confirmed that "wait once then read" is fragile for post-turn writes; **poll a window, don't snapshot once.** (The affect.emit write, by contrast, DID land inside the 35s window — promotion is the slower of the two post-turn writes.) diff --git a/persistent-memory.d/2026-06-29-bifrost-repinned-1-0-0-v0-18-2-af67ad9.md b/persistent-memory.d/2026-06-29-bifrost-repinned-1-0-0-v0-18-2-af67ad9.md new file mode 100644 index 0000000..7194b03 --- /dev/null +++ b/persistent-memory.d/2026-06-29-bifrost-repinned-1-0-0-v0-18-2-af67ad9.md @@ -0,0 +1 @@ +`[2026-06-29]` **bifrost repinned 1.0.0 (`v0.18.2`, `af67ad9`).** bifrost-dev shipped its first stable release; wire v0.6 now STABLE/FROZEN. Non-breaking (byte-identical to 0.10.0); switched the floor pin → exact `==1.0.0` per the stable-substrate posture. Post-1.0 breaking changes ride a bifrost MAJOR + new wire (v0.7+); a v0.6-pinned consumer is stable indefinitely. (Also this session: althing migrated to v0.15.0+ lean-bus / schema v4 — moderation retired, chamber/redis ripped; our tooling auto-updated to 0.17.4.) diff --git a/persistent-memory.d/2026-06-29-web-spa-combined-bind-default-v0-18-1-719e4d6.md b/persistent-memory.d/2026-06-29-web-spa-combined-bind-default-v0-18-1-719e4d6.md new file mode 100644 index 0000000..7d374b3 --- /dev/null +++ b/persistent-memory.d/2026-06-29-web-spa-combined-bind-default-v0-18-1-719e4d6.md @@ -0,0 +1 @@ +`[2026-06-29]` **Web SPA combined-bind default (`v0.18.1`, `719e4d6`) — operator-caught gap.** #18 shipped the composite `:8392` provider but never exposed it in the web bind dropdown (only memory/affect single-plane). Added `combined (:8392)` as the DEFAULT option (both planes in one session), kept single-plane for isolation diagnostics; wired `endpoint_for_plane` combined→8392 + server validation + the dropdown. Direct TDD; #17 contract updated (the governing spec for the web bind). Restarted `:8765` on current code (env.sh + provider.env + `RATATOSKR_AFFECT_READ_URL=:8392`). diff --git a/persistent-memory.d/2026-06-30-b-tier-1-frontier-scoped-ready-for-a-contract.md b/persistent-memory.d/2026-06-30-b-tier-1-frontier-scoped-ready-for-a-contract.md new file mode 100644 index 0000000..5358cbd --- /dev/null +++ b/persistent-memory.d/2026-06-30-b-tier-1-frontier-scoped-ready-for-a-contract.md @@ -0,0 +1 @@ +`[2026-06-30]` **(b) Tier-1 frontier SCOPED, ready for a contract-first TDD cycle (next focused work).** The primitives already exist + are contracted + tested; the gap is PRESENTER-level wiring. Two slices: **(b1) SSE-resume** — contract #1 (`ratatoskr.sse_client`) DELIBERATELY makes resume caller-owned ("on `SseConnectionDropped`, the caller MAY invoke `reconnect_turn`"); `reconnect_turn` (sse_client.py:524) has NO caller. Gap = a SHARED resume-orchestration wrapper (catch `SseConnectionDropped` → track last-seen `sse_id` → `reconnect_turn` → continue), consumed by all 3 presenters per design-brief §8b "share the consumer, branch the presenter" (NOT per-presenter — that forks the consumer). New function block → **amend contract #1** (additive FN, e.g. `stream_turn_resilient`) then TDD (RED: drop-mid-stream→resume continuity; GREEN: wrapper; wire `cli --send` first as the tracer). Resume design pre-locked: in-process Last-Event-ID only, cross-process deferred to v2 (design-brief §8d). **(b2) session-picker** — `list_sessions` (sessions.py:198) has NO caller; add a Textual DataTable startup picker (>1 session) + `--session `/`--new` CLI flags (design-brief §4, decisions pre-locked). Both pre-locked → heid-contract-review likely skippable as ceremony (small additive amendments to mature specs); heid-code-review still valuable. **#11 AdminEvents stays BLOCKED** on `admin.events.read` scope (infra-ops). diff --git a/persistent-memory.d/2026-06-30-b1-sse-resume-shipped-v0-18-5-streamturnresil.md b/persistent-memory.d/2026-06-30-b1-sse-resume-shipped-v0-18-5-streamturnresil.md new file mode 100644 index 0000000..5b8e3a6 --- /dev/null +++ b/persistent-memory.d/2026-06-30-b1-sse-resume-shipped-v0-18-5-streamturnresil.md @@ -0,0 +1 @@ +`[2026-06-30]` **(b1) SSE-resume SHIPPED (`v0.18.5`) — `stream_turn_resilient` (sse_client.py).** The shared resume-orchestration surface (design-brief §8b): wraps `stream_turn`+`reconnect_turn`, catches `SseConnectionDropped` (mid-stream drop OR clean-EOF-before-terminal) → resumes from last-seen `sse_id` via `reconnect_turn` (Last-Event-ID), up to `max_reconnects` (default 5); non-drop reconnect failures (412/410/400/TurnIdFlip/SseConnectFailed) PROPAGATE per contract #1's "surface, not recover". `last_seen` persists ACROSS attempts (a zero-event reconnect drop falls back to the prior attempt's id). Direct in-session TDD against a contract-#1 amendment (8 cases incl. two-drops, max-reconnects-exhausted, zero-budget, buffer-expired-propagates, unresumable-zero-event). Wired ALL THREE presenters through it (`v0.18.6`): `cli --send` (`cli.py:396`), TUI (`tui.py:1321`), web (`web/server.py:294`) — each a name-for-name `stream_turn`→`stream_turn_resilient` swap (the §8b "all presenters share the consumer" promise, fully kept; the TUI is the primary resume beneficiary — long-lived sessions / laptop-suspend). Suite 518 green; ruff+mypy clean on touched code (pre-existing cli.py:400/543 mypy warts left untouched per surgical rule); contract #1 validates OK. **heid-code-review NOT run** (small additive well-TDD'd wrapper; offered to operator). **b2 (session-picker + `--session`/`--new` flags) still pending.** diff --git a/persistent-memory.d/2026-06-30-b2-session-picker-shipped-v0-18-7-bare-tui-mo.md b/persistent-memory.d/2026-06-30-b2-session-picker-shipped-v0-18-7-bare-tui-mo.md new file mode 100644 index 0000000..ee3d1f0 --- /dev/null +++ b/persistent-memory.d/2026-06-30-b2-session-picker-shipped-v0-18-7-bare-tui-mo.md @@ -0,0 +1 @@ +`[2026-06-30]` **(b2) session-picker SHIPPED (`v0.18.7`) — bare TUI mode → startup picker (design-brief §4).** `list_sessions` had NO caller; now bare TUI mode (no `--session`/`--new`) resolves via `list_sessions` in `_resolve_then_run`: **0 sessions → `[no_sessions]` error, exit 14** (resume-only, honors §4 "no in-app session creation — `--new` flag only"); **exactly 1 → auto-resume** (§4 "picker only when >1"); **≥2 → new `SessionPickerApp`** (Textual `App[str|None]`, mirrors `AgentPickerApp`; ListView of sessions) → resume the pick (Esc/Ctrl-D → exit 0). cli `_parse` relaxed: bare TUI now VALID (was "pass exactly one" error); `--send` still requires one flag (non-interactive, no picker); `--agent` forbidden in bare mode; `run_tui` PRE-002 XOR→"not both". Direct in-session TDD (contract #6 amendment, validated OK): 3 widget pilot tests + 5 `_resolve_then_run` resolution tests + 3 cli validation tests. Suite **528 green**; touched code ruff-clean (mypy: only the `BINDINGS` list-invariance warning every App in tui.py already carries — consistent). **DESIGN NOTE — bare+0-sessions → error (clause-consistent). The friendlier auto-fall-through-to-new alternative is DEFERRED pending operator preference (it would create a session without `--new`, against the §4 negative clause).** **Frontier now: `GET /capabilities`+`GET /me` → BifrostState/Tools widgets (`GET /admin/sessions/{id}/{bifrost,tools}`, admin-key) → #11 AdminEvents (BLOCKED on `admin.events.read`).** heid-code-review NOT run on b1 or b2 (offered). diff --git a/persistent-memory.d/2026-06-30-capabilities-me-slice-shipped-v0-18-8-get-me.md b/persistent-memory.d/2026-06-30-capabilities-me-slice-shipped-v0-18-8-get-me.md new file mode 100644 index 0000000..b451549 --- /dev/null +++ b/persistent-memory.d/2026-06-30-capabilities-me-slice-shipped-v0-18-8-get-me.md @@ -0,0 +1 @@ +`[2026-06-30]` **capabilities+me slice SHIPPED (`v0.18.8`) — `GET /me` + `GET /capabilities` consumed via a new `--whoami` one-shot.** `get_me`/`get_capabilities` added to sessions.py (mirror `get_persona_state`: 200→dict verbatim, non-200→`SessionApiFailed`; freeform dicts per the frozen OpenAPI). New `ratatoskr --whoami` CLI mode (mirrors `--send`'s non-interactive shape) fetches both + prints an identity+capabilities report; standalone probe (mutually exclusive with `--send`/`--session`/`--new`/`--agent`, opens no session; new `ParsedArgs.whoami` field + main() dispatch). **`/capabilities` is the Echo EPHEMERAL-TEMPLATE discovery endpoint** (`{ephemeral_templates:{echo:{allowed_models,default_model,system_prompt_max_bytes}}}`), NOT a generic server-caps endpoint (audit finding — the coverage-map's earlier "server capability discovery" framing was imprecise). `/me` = whoami (`{user_id,scopes,tier,key_id?,...}`, optionals omitted-not-null). Contract-skip privilege invoked (low-effort GET wrappers) but contract #2 amended (2 FNs, validated OK) to keep the sessions spec canonical + honest test citations. TDD: 5 wrapper tests + 5 cli tests (validation + mode + error). Suite **538 green**; touched code ruff-clean (mypy: only `no-any-return` on `resp.json()`→dict, identical to the pre-existing `get_persona_state`). **Coverage: REST 9/40 ✅ (up from 7).** TUI-surfacing of /me (footer identity line) + /capabilities DEFERRED — the one-shot is the minimal tracer. **Frontier now: BifrostState + Tools widgets (`GET /admin/sessions/{id}/{bifrost,tools}`, admin-key-gated) → #11 AdminEvents (BLOCKED on `admin.events.read`).** diff --git a/persistent-memory.d/2026-06-30-finding-p-1-pin-drift-pin-remediation-pending.md b/persistent-memory.d/2026-06-30-finding-p-1-pin-drift-pin-remediation-pending.md new file mode 100644 index 0000000..5793a56 --- /dev/null +++ b/persistent-memory.d/2026-06-30-finding-p-1-pin-drift-pin-remediation-pending.md @@ -0,0 +1 @@ +`[2026-06-30]` **Finding P-1 (pin drift) + pin-remediation PENDING.** We vendor the PROSE markdown (`docs/conversation-api-spec.md`), which is **byte-identical to live WT's** but frozen at v0.35.16-era content (last WT edit 2026-05-31) — it does NOT capture b2: 7 new endpoints (admin/keys/bulk, admin/persona/{archive,erase}, admin/usage, embed, judgments, me/usage), the 409/503 on messages-POST (#331), the unified error envelope (#328), or the SSE schema. **WT's authoritative v1 truth is now the FROZEN OpenAPI 2.2.0 + SSE-schema JSON** (`Worldtree/docs/v1-schema-freeze-manifest.md`). So the previously-deferred "re-vendor markdown to b2" is a **near-no-op** (markdown content identical). **Pending operator nod:** re-pin to the machine-readable artifacts (recommended — drift-checkable via `canonical_drift.py`, makes the coverage map reproducible vs a frozen diffable target) vs markdown-only. Deferred (not auto-applied) because it adds vendored artifacts + a canonical-sync pin = substrate change with CI-gating reach. **→ RESOLVED 2026-06-30 (operator: "a then b").** Vendored `conversation-api-openapi.json` (2.2.0) + `conversation-api-sse-events.schema.json` + re-copied the prose markdown; pinned all three in `.corviduo-canonicals.toml` (OpenAPI+SSE = strict drift gates, markdown = `tolerate_drift` reference); advanced `worldtree-spec-rev` f1b59f8→5810a26 + `worldtree-version` v0.29.0(STALE, never bumped from the v0.35.16 pin)→v1.0.0b2 + `pinned-on`→2026-06-30; SPEC-PIN.md history row added. `canonical_drift.py` green (10/10). `pin:`-only, no version bump (no client-facing code change; the b2 409/503 + error-envelope were already consumed in v0.18.3/.4). diff --git a/persistent-memory.d/2026-06-30-heimdall-keys-are-per-instance-a-key-minted-o.md b/persistent-memory.d/2026-06-30-heimdall-keys-are-per-instance-a-key-minted-o.md new file mode 100644 index 0000000..7ba8d64 --- /dev/null +++ b/persistent-memory.d/2026-06-30-heimdall-keys-are-per-instance-a-key-minted-o.md @@ -0,0 +1 @@ +`[2026-06-30]` **Heimdall keys are PER-INSTANCE — a key minted on one Worldtree 401s on another.** Our Conversation-API key works on personal `:8081` but 401s `auth_invalid` on demo `:8080` (per-instance Heimdall user store + pepper; fresh deploys start with an EMPTY key store). Same as the admin key (personal-only). **To live-drive a given instance you need a key minted FOR that instance** (request via infra-ops). Couldn't live-prove the b2 409 on demo for this reason → deferred to personal-b2 where we have access. diff --git a/persistent-memory.d/2026-06-30-regard-is-a-dead-axis-in-worldtree-s-emitted.md b/persistent-memory.d/2026-06-30-regard-is-a-dead-axis-in-worldtree-s-emitted.md new file mode 100644 index 0000000..5df77b2 --- /dev/null +++ b/persistent-memory.d/2026-06-30-regard-is-a-dead-axis-in-worldtree-s-emitted.md @@ -0,0 +1 @@ +`[2026-06-30]` **regard is a DEAD AXIS in Worldtree's emitted affect (caught provider-side; worldtree-dev confirmed + escalated to Vuong).** Across all our affect snapshots, `valence[].regard` is EXACTLY 0.15 regardless of agent/end_user/interaction_count, while familiarity accumulates (vuong 0.18→0.69 over 14 turns). Root cause (worldtree-dev, code-grounded): 0.15 = `base_regard = agreeableness*0.3` (sindra A=0.5); regard's only human-writer `update_regard` early-returns unless an emotion is `about="other"`, but the Vili appraiser's `ViliResponse` schema has NO directedness axis (everything hardcoded `about="situation"`) — producer side lost in the #265 Vili rework; consumer machinery intact. NOT WAD; the fix (reintroduce other-directed classification) is an affect-model change touching every agent + a directedness-classification design call → worldtree-dev filing an issue to Vuong. [the consumer/provider thesis paying off again] diff --git a/persistent-memory.d/2026-06-30-scope-mandate-a-locked-operator-v1-done-every.md b/persistent-memory.d/2026-06-30-scope-mandate-a-locked-operator-v1-done-every.md new file mode 100644 index 0000000..c1f01d7 --- /dev/null +++ b/persistent-memory.d/2026-06-30-scope-mandate-a-locked-operator-v1-done-every.md @@ -0,0 +1 @@ +`[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.** The coverage map is a LEDGER, not a build-everything mandate. Reconciles the 2026-06-19 "consume all I/O" reframe with the 2026-05-20 design-brief's "NOT an admin tool" + deferral negative clauses (which predate both the provider identity and the reframe). Resolved the 11 design-brief-vs-reframe ❓ rows via the debug-observability test (*does a turn flow through it?*): 🚫 search / uploads / pending / embed / judgments (consumer-product + eval utilities); ⬜ transient-characters routing (4) + persona_state-write (Tier-2 frontier). **Frontier Tier 1 (all unblocked except #11):** session-picker + SSE-resume (wrappers `list_sessions`/`reconnect_turn` exist with NO caller — presenter-wiring only) → `GET /capabilities` + `GET /me` → BifrostState/Tools widgets (`GET /admin/sessions/{id}/{bifrost,tools}`, admin-key) → **#11 AdminEvents BLOCKED on `admin.events.read` scope**. The 3 admin-observability widgets + picker + resume were design-brief §5/§4/§8d v1 items that **were never built**. diff --git a/persistent-memory.d/2026-06-30-tea-comment-n-hangs-on-gitea.md b/persistent-memory.d/2026-06-30-tea-comment-n-hangs-on-gitea.md new file mode 100644 index 0000000..ae0da77 --- /dev/null +++ b/persistent-memory.d/2026-06-30-tea-comment-n-hangs-on-gitea.md @@ -0,0 +1 @@ +`[2026-06-30]` **`tea comment ` hangs on Gitea** (the whole compound bash auto-backgrounded + stuck on the open `tea` call). The #11 prereq comment hung; killed it + posted via the Gitea HTTP API directly (`POST /api/v1/repos/vh/ratatoskr/issues//comments`, token from `~/.config/tea/config.yml`). **For issue comments, prefer the Gitea API over `tea comment` when `tea` is flaky** (CLAUDE.md already says use HTTP for comment-EDITS; this extends it to ADD when tea hangs). Verify-then-post (check the comment didn't already land) to avoid a double-post after a kill. diff --git a/persistent-memory.d/2026-06-30-v1-coverage-audit-kicked-off-coverage-ledger.md b/persistent-memory.d/2026-06-30-v1-coverage-audit-kicked-off-coverage-ledger.md new file mode 100644 index 0000000..81708b5 --- /dev/null +++ b/persistent-memory.d/2026-06-30-v1-coverage-audit-kicked-off-coverage-ledger.md @@ -0,0 +1 @@ +`[2026-06-30]` **v1 coverage-audit kicked off; coverage ledger written (`docs/coverage-map.md`) — the first one.** Every Worldtree v1-FROZEN I/O point × ratatoskr status. Anchored on WT's frozen machine-readable artifacts (OpenAPI **2.2.0** `conversation-api-openapi.json` = 40 REST path-groups + SSE schema = 11 events + bifrost wire v0.6), NOT the stale vendored prose markdown. Result: **SSE 11/11 ✅; Bifrost provider planes 8/8 ✅ live-proven** (covers the full `bifrost.memory.MemoryDataStore` protocol = describe_store/get/get_many/search/upsert_many + delete_many, and affect emit/fetch; **`health` is extended-reference-store-only, NOT in the base protocol → correctly deferred, NOT a gap** — settles the prior "health" ambiguity); **client REST 7/40 ✅ live, 11 ⬜ in-scope, 22 🚫 excluded.** diff --git a/persistent-memory.d/2026-06-30-verify-against-the-real-spec-before-committin.md b/persistent-memory.d/2026-06-30-verify-against-the-real-spec-before-committin.md new file mode 100644 index 0000000..fe27d84 --- /dev/null +++ b/persistent-memory.d/2026-06-30-verify-against-the-real-spec-before-committin.md @@ -0,0 +1 @@ +`[2026-06-30]` **Verify-against-the-real-spec-before-committing caught a real upstream gap.** Holding the v0.18.3 commit to verify against demo's OpenAPI surfaced that the FROZEN OpenAPI 2.1.0 didn't document the 409/503 the heads-up described (`agent_not_available` was in the ErrorCode enum, but NO 503/turn-launch code). worldtree-dev confirmed it was THEIR gap (#331 added the statuses without extending the #328 `openapi()` override), shipped the fix in **v1.0.0b2 / OpenAPI 2.2.0** (409/503 now enumerated, 503 code finalized as `not_ready`). "The consumer-oracle earning its keep." Lesson: a provider's prose heads-up can diverge from its frozen machine-readable spec — verify the actual spec before committing a consumer adaptation. diff --git a/persistent-memory.d/2026-06-30-worldtree-v1-0-0b1-b2-consumer-adaptation-eag.md b/persistent-memory.d/2026-06-30-worldtree-v1-0-0b1-b2-consumer-adaptation-eag.md new file mode 100644 index 0000000..2bdff78 --- /dev/null +++ b/persistent-memory.d/2026-06-30-worldtree-v1-0-0b1-b2-consumer-adaptation-eag.md @@ -0,0 +1 @@ +`[2026-06-30]` **Worldtree v1.0.0b1→b2 consumer adaptation: eager turn-launch statuses (`v0.18.3` `b2e4901`, `v0.18.4` `e4317f6`).** Worldtree #331 decoupled turn execution from the SSE connection → turn-launch failures now arrive EAGERLY as a status before any stream: 409 `agent_not_available` (pre-b1 a 200 + in-stream error event), 503 retryable. Mapped both in `stream_turn` to typed `SseConnectFailed` subclasses keyed on STATUS, parsing the `{detail:{error_code,message}}` envelope — POST-003 preserved (no synthetic event yielded), existing handlers still catch (the design fork vs yield-an-Error-event was decided by POST-003). **DEFERRED follow-ups** (tracked here; bundle with the v1 coverage-audit): (1) live-prove the 409/503 end-to-end on personal-b2 (now unblocked — personal on b2, my key works there); (2) full `conversation-api-spec.md` markdown re-vendor to the b2 era (ratatoskr vendors the markdown, not the OpenAPI JSON). diff --git a/persistent-memory.d/2026-07-01-adminevents-pane-shipped-v0-18-11-get-admin-e.md b/persistent-memory.d/2026-07-01-adminevents-pane-shipped-v0-18-11-get-admin-e.md new file mode 100644 index 0000000..beea4bc --- /dev/null +++ b/persistent-memory.d/2026-07-01-adminevents-pane-shipped-v0-18-11-get-admin-e.md @@ -0,0 +1 @@ +`[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.** `stream_admin_events(client, *, admin_key, last_event_id=None)` (sse_client.py) — a NEW long-lived SSE consumer for the admin lifecycle broadcast (envelope `{id,type,timestamp,data}`, 17-event v0 vocab), admin-scoped (`admin.events.read`, bearer-override), Last-Event-ID resume; non-200→SseConnectFailed, mid-drop→SseConnectionDropped; new `AdminEvent` dataclass (distinct from the turn `Event` union). New "AdminEvents" TabPane + `_format_admin_event` + `_admin_event_matches` (design-brief §6 filter: active-session events + non-heartbeat `system.*`) + `_stream_admin_events` long-lived best-effort worker (unconditional on_mount, cancelled on app exit; self-labels "not configured"/"unavailable"/"stream ended"). Reuses the admin key from the BifrostState slice. **Contract-SKIPPED** for `stream_admin_events` (out of contract #1's turn-SSE scope; spec § Admin Event Stream is the reference; well-TDD'd). TDD: 4 sse_client tests (multi-event+bearer-override, Last-Event-ID header, 403, malformed-skip) + 5 tui (format, filter, worker success/no-key/403). Suite **561 green**; my code ruff-clean (pre-existing tui.py ruff debt untouched, incl. the dead `RichText` import in `_hydrate_persona`). **LIVE-AUTH-PROVEN**: `GET /admin/events` on :8081 → HTTP 200 under the admin key (connected + streamed, idle in the 4s window — no 401/403). **Coverage: REST 12/40 ✅. Tier 1 admin/debug-observability core COMPLETE** (Persona · Tools · BifrostState · AdminEvents). AdminEvents work landed as patch `v0.18.11`; then **`v0.19.0` MINOR cut (operator-approved 2026-07-01)** publishing the milestone: **the debug-observability core is complete** (Persona · Tools · BifrostState · AdminEvents all built + consuming real endpoints — the design-brief's headline deliverable). Pre-1.0 minor = release-note-worthy (no downstream althing push needed pre-1.0); lightweight tag per the SemVer mechanics (annotated reserved for major cuts). Remaining in-scope client I/O: only Tier-2 (transient-characters routing + `POST /sessions/{id}/persona_state`). diff --git a/persistent-memory.d/2026-07-01-affect-snapshot-shape-changed-valence-relatio.md b/persistent-memory.d/2026-07-01-affect-snapshot-shape-changed-valence-relatio.md new file mode 100644 index 0000000..4f9dd61 --- /dev/null +++ b/persistent-memory.d/2026-07-01-affect-snapshot-shape-changed-valence-relatio.md @@ -0,0 +1 @@ +`[2026-07-01]` **Affect snapshot shape CHANGED valence→relations (relation_edge/1) — the persona pane was reading a dead field.** Worldtree's #265 Vili rework replaced the flat `valence[]` ({entity_id,familiarity,regard}) with `relations[]` (target_entity + trust_ability/benevolence/integrity + warmth + agency + relation_context, each `{value,confidence,evidence_count}`). `renderAffectPane` still read `snap.valence` → showed empty "valence (0)". Rebuilt to render `relations` (v0.19.4, `ca46a93`) with per-value **Δ + unicode sparkline** (client-side, HIST_CAP=24, one sample/turn deduped by emitted_at). **Retires the stale "regard dead axis" note (2026-06-30) — that whole axis is gone.** Foot-gun: the affect snapshot shape is Worldtree's emit and can change under us — verify the live shape (query affect.db) before trusting a render. diff --git a/persistent-memory.d/2026-07-01-b1-sse-resume-heid-code-review-panel-zero-fin.md b/persistent-memory.d/2026-07-01-b1-sse-resume-heid-code-review-panel-zero-fin.md new file mode 100644 index 0000000..4ea75ab --- /dev/null +++ b/persistent-memory.d/2026-07-01-b1-sse-resume-heid-code-review-panel-zero-fin.md @@ -0,0 +1 @@ +`[2026-07-01]` **b1 (SSE-resume) heid-code-review panel: ZERO findings — cross-model-verified clean.** Gróa (Grok) + Hulda (Codex) + Regin (GLM-5.2) each independently reviewed `stream_turn_resilient` vs contract #1's amendment (artifact-only, firewall held) → all three ZERO findings; signature / PRE-001..004 / STEP 1-4 / POST-001..003 / ERROR_ROUTING / all-8-TESTS confirmed, incl. the subtle `seen = last_seen or drop.last_seen_sse_id` zero-event-drop fallback. Convergent meta-note: **TDD + the unusually-prescriptive contract (STEPS `flexibility=prescriptive` + explicit GOTO) left no room for compliant-but-different drift — confirmation, not discovery.** Calibration signal: for a thin wrapper with a tight prescriptive contract + comprehensive TDD, the panel confirms rather than discovers. **b2 (picker) + capabilities+me NOT yet reviewed** (higher-surface b2 is the better candidate if more review is wanted). Dispatch msg `01KWE2K99T…` / thread `01KWE2K99S…`; heid dispatch-log `2026-06.jsonl#01KWE2V3MMY8XS55FCJYXYV14B`. diff --git a/persistent-memory.d/2026-07-01-bifroststate-pane-shipped-v0-18-10-get-admin.md b/persistent-memory.d/2026-07-01-bifroststate-pane-shipped-v0-18-10-get-admin.md new file mode 100644 index 0000000..1b87352 --- /dev/null +++ b/persistent-memory.d/2026-07-01-bifroststate-pane-shipped-v0-18-10-get-admin.md @@ -0,0 +1 @@ +`[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.** `get_session_bifrost(client, session_id, *, admin_key)` (sessions.py) — admin-scoped (`admin.sessions.read`); the request OVERRIDES Authorization with `admin_key` (distinct from the consumer bearer, asserted in a test); 200→dict, non-200→SessionApiFailed. Admin-key wiring: `--admin-key` flag + `RATATOSKR_ADMIN_API_KEY` env → new `ParsedArgs.admin_key`. New "Bifrost" TabPane + `_format_bifrost_state` + `_hydrate_bifrost_state` best-effort worker (mirror `_hydrate_session_tools`) UNCONDITIONALLY in on_mount → writes {endpoint, connected, caps_granted, tools} + audits; self-labels "not configured" (no admin key) / "not bound" (404) / graceful on 403 + error. Contract #2 amended (FN, validated OK) + TDD (4 wrapper respx tests incl. the admin-bearer-override assertion + 1 format unit + 3 hydrate integration). Suite **552 green**; my code ruff-clean (pre-existing tui.py ruff debt at other lines untouched, incl. a dead `RichText` import in `_hydrate_persona`). **LIVE-AUTH-PROVEN** on personal :8081: admin key authenticated (reached resource-layer 404 session_not_found, NOT 401/403) → `admin.sessions.read` works live; 200 full-state not exercised (no bound session on :8081 now — unit-covered). Patch bump (debug feature, no downstream coordination; consistent with the session's cadence — but the §5-core-completion angle is a possible minor, operator's call). diff --git a/persistent-memory.d/2026-07-01-canonical-check-blocked-an-accesstally-fork-r.md b/persistent-memory.d/2026-07-01-canonical-check-blocked-an-accesstally-fork-r.md new file mode 100644 index 0000000..20c6935 --- /dev/null +++ b/persistent-memory.d/2026-07-01-canonical-check-blocked-an-accesstally-fork-r.md @@ -0,0 +1 @@ +`[2026-07-01]` **Canonical check BLOCKED an access_tally fork (reference-impl posture held).** I'd offered to wire `access_tally`-on-search into our store for the recall-utility label; checked bifrost's reference first (`get`/`search` are PURE-READ, no access tracking — those are Worldtree's chunk-schema fields, not bifrost's contract) → wiring it would fork behavior the canonical reference lacks. Did NOT wire it; routed recall-instrumentation to Worldtree's layer (owns the recall event) or a bifrost-dev protocol ask. [reinforces `feedback-debug-surface-uses-canonical-surface-only`] diff --git a/persistent-memory.d/2026-07-01-embedding-latency-loop-resolved-it-was-worldt.md b/persistent-memory.d/2026-07-01-embedding-latency-loop-resolved-it-was-worldt.md new file mode 100644 index 0000000..76378d4 --- /dev/null +++ b/persistent-memory.d/2026-07-01-embedding-latency-loop-resolved-it-was-worldt.md @@ -0,0 +1 @@ +`[2026-07-01]` **Embedding-latency loop RESOLVED — it was WORLDTREE's, not ratatoskr (the consumer/provider thesis paid off again).** Vuong flagged dozens of embed queries/Tier-3 turn; worldtree-dev's first-pass blamed our memory_context chunk-batching. Traced CODE-SIDE that ratatoskr embeds ZERO times (provider `upsert_many` stores the given embedding, `search` takes a given vector, the conversation consumer POSTs only `{content}`, `/embed` is coverage-map-excluded — pure Bifrost/ADR-0009 path, WT does all embedding). worldtree-dev retracted + fixed on THEIR side (`v1.0.0b4`): a persona-recitation memory-gate re-embedding the stable character card sentence-by-sentence every turn (~95% of gateway traffic) → content-hash cache; re-embed ratio 15x→1.01x. **Lesson: verify your own code before accepting a peer's "it's your side" — the debug tool proving its own side clean is the whole point.** diff --git a/persistent-memory.d/2026-07-01-env-sh-now-persists-the-web-bifrost-bind-vars.md b/persistent-memory.d/2026-07-01-env-sh-now-persists-the-web-bifrost-bind-vars.md new file mode 100644 index 0000000..0460812 --- /dev/null +++ b/persistent-memory.d/2026-07-01-env-sh-now-persists-the-web-bifrost-bind-vars.md @@ -0,0 +1 @@ +`[2026-07-01]` **env.sh now PERSISTS the web Bifrost-bind vars (gitignored, local-only).** `ratatoskr-web`'s in-browser bind needs three server-held values; env.sh sources `provider.env` for the Heimdall key and exports `RATATOSKR_BIFROST_CONSUMER_KEY` + `RATATOSKR_PROVIDER_VISIBLE_HOST=10.100.10.50` + `RATATOSKR_AFFECT_READ_URL=:8392`. **The HS256 byte-match trap (re-hit + documented):** the bind's consumer key must equal the key the `:8392` combined provider validates against = `RATATOSKR_HEIMDALL_KEY` (provider.env, fp `45a0…`), NOT `WORLDTREE_API_KEY` (env.sh, fp `7c2f…`) — both are the SAME `ratatoskr` identity but DIFFERENT 40-char strings; signing with the wrong one → `bifrost.auth_rejected`. Single-sourced (env.sh sources provider.env) to avoid a rotation footgun; guarded with a stderr warning if provider.env is missing. [auto-memory: HS256-key-is-the-consumer-Heimdall-key-string] diff --git a/persistent-memory.d/2026-07-01-foot-gun-measurement-self-caught-before-flagg.md b/persistent-memory.d/2026-07-01-foot-gun-measurement-self-caught-before-flagg.md new file mode 100644 index 0000000..4505ce7 --- /dev/null +++ b/persistent-memory.d/2026-07-01-foot-gun-measurement-self-caught-before-flagg.md @@ -0,0 +1 @@ +`[2026-07-01]` **Foot-gun (measurement, self-caught before flagging): establish the baseline before claiming a rate.** Nearly flagged "aggressive over-promotion (55 chunks / 7 turns)" to worldtree-dev — but the chunks spanned the whole 5-hour session (~1/turn), not 7 turns; I'd assumed memory.db was 0 immediately before the probe when it had been accumulating since the reset. Caught it via `created_at` spread before the flag went out. Also: the promoted corpus was the operator's ERP *test* content (wiped after each test) — not a privacy issue, but abstract test content out of any peer-shared diagnostic. diff --git a/persistent-memory.d/2026-07-01-get-sessions-id-tools-quick-win-shipped-v0-18.md b/persistent-memory.d/2026-07-01-get-sessions-id-tools-quick-win-shipped-v0-18.md new file mode 100644 index 0000000..4bd1d48 --- /dev/null +++ b/persistent-memory.d/2026-07-01-get-sessions-id-tools-quick-win-shipped-v0-18.md @@ -0,0 +1 @@ +`[2026-07-01]` **`GET /sessions/{id}/tools` quick-win SHIPPED (`v0.18.9`) — owner-scoped tool inventory in the TUI Tools pane.** `get_session_tools` wrapper (sessions.py, mirror get_me: 200→dict, non-200→`SessionApiFailed`) + `_format_tool_inventory` helper + `_hydrate_session_tools` best-effort worker (mirror `_hydrate_persona`) wired UNCONDITIONALLY in `on_mount` → writes the merged `{agent_id, builtin_tools, bifrost_tools}` inventory (what the LLM saw at turn-fire) to the Tools pane + audits `session_tools_hydrated`, never crashes on failure. Owner-scoped (`ctx.user_id==session.user_id`) → reachable with the CONSUMER key, NO admin scope — so this **covers the design-brief §5 "Tools widget" via the reachable owner endpoint** (the admin `/admin/sessions/{id}/tools` variant stays a gap only for cross-user operator debug). Contract #2 amended (FN, validated OK) + TDD (3 wrapper respx tests + 1 format-helper unit + 2 hydrate integration tests via `_spy_writes`+pilot). Suite **544 green**; touched code ruff-clean (the tui.py ruff/mypy debt at other lines is pre-existing). **Coverage: REST 10/40 ✅.** **Frontier now: BifrostState widget (`GET /admin/sessions/{id}/bifrost`, admin-key) + #11 AdminEvents (BLOCKED on `admin.events.read`) + Tier-2 (transient-characters routing, `POST /sessions/{id}/persona_state`).** diff --git a/persistent-memory.d/2026-07-01-heid-code-review-v0-19-3-75dec01-panel-caught.md b/persistent-memory.d/2026-07-01-heid-code-review-v0-19-3-75dec01-panel-caught.md new file mode 100644 index 0000000..dfa7b01 --- /dev/null +++ b/persistent-memory.d/2026-07-01-heid-code-review-v0-19-3-75dec01-panel-caught.md @@ -0,0 +1 @@ +`[2026-07-01]` **heid-code-review (`v0.19.3`, `75dec01`) — panel caught 2 real client-side SSE-lifecycle bugs TDD missed.** Contract-anchored (authored the web contract to enable it — no contract → no drift axis). Gróa/Hulda/Regin (artifact-only, Gróa under Landlock jail): ZERO functional server-side drift + INV-004 clean; 2 genuine drifts on the un-unit-tested SPA — (1) turn `es.onerror` didn't `hideThinkingNote()` (reasoning line + setInterval leak on a raw drop), (2) `openAdminEvents` never closed the EventSource on error → native auto-reconnect RETRY LOOP (fixed: close on `stream_error` + permanent `onerror`/CLOSED; transient CONNECTING still reconnects). + 2 test-gaps fixed (route-registration + admin stream_error). 1 precision → contract-clarified (tools-inventory names-only by design). **Re-confirms: the JS render/lifecycle paths are the review's highest-value target — unit tests don't reach them (same lesson as #18 D2).** diff --git a/persistent-memory.d/2026-07-01-ledger-correction-11-adminevents-is-no-longer.md b/persistent-memory.d/2026-07-01-ledger-correction-11-adminevents-is-no-longer.md new file mode 100644 index 0000000..064fd7c --- /dev/null +++ b/persistent-memory.d/2026-07-01-ledger-correction-11-adminevents-is-no-longer.md @@ -0,0 +1 @@ +`[2026-07-01]` **LEDGER CORRECTION: #11 (AdminEvents) is NO LONGER BLOCKED.** Verified via `GET /me` on :8081 that `RATATOSKR_ADMIN_API_KEY` (`ratatoskr-readonly`, tier readonly-admin) carries ALL 7 read scopes INCLUDING **`admin.events.read`** (+ `admin.sessions.read`, admin.keys.read, admin.skuld.read, pending.read, search.read, tool_events.read). The coverage-map + prior memory had #11 "blocked on admin.events.read" — **STALE**; the admin key was minted (post-#11-filing, env.sh) WITH the scope, so the blocker is already satisfied. **Only the AdminEvents SSE pane itself is unbuilt** — the last unbuilt §5 debug pane (a live SSE-consuming admin pane, distinct from the hydrate-at-attach panes). Coverage-map updated. **Coverage: REST 11/40 ✅.** Consider building the AdminEvents pane and/or updating #11's tracker status (its stated blocker is gone). diff --git a/persistent-memory.d/2026-07-01-memory-plane-proven-healthy-end-to-end.md b/persistent-memory.d/2026-07-01-memory-plane-proven-healthy-end-to-end.md new file mode 100644 index 0000000..ddd7b5f --- /dev/null +++ b/persistent-memory.d/2026-07-01-memory-plane-proven-healthy-end-to-end.md @@ -0,0 +1 @@ +`[2026-07-01]` **Memory plane PROVEN healthy end-to-end.** Seed a novel fact → promotion → COLD (history-free) session recall of the exact fact (injected as MEMORY:DATA, confidence 0.74, verbatim, no #296 subject-inversion). The memory round-trip (the other half of the Bifrost provider identity) works cleanly on the reset slate. diff --git a/persistent-memory.d/2026-07-01-persona-pane-displays-the-canonical-affect-nl.md b/persistent-memory.d/2026-07-01-persona-pane-displays-the-canonical-affect-nl.md new file mode 100644 index 0000000..868f7b9 --- /dev/null +++ b/persistent-memory.d/2026-07-01-persona-pane-displays-the-canonical-affect-nl.md @@ -0,0 +1 @@ +`[2026-07-01]` **Persona pane displays the CANONICAL affect→NL Worldtree injects — ADOPT, don't invent (operator steer + reference-impl posture).** Worldtree's `describe_pad` (mood word, valence×arousal grid, ±0.3 bands) + `render_d2_canonical` (relationship directive) are deterministic + canon-driven; the pane now renders them **byte-exact-verified** against Worldtree's own renderer on the live snapshot (v0.19.5, `a99f247`). KEY LESSON: adopting canonical is load-bearing — for sindra's small PAD the canonical says **"neutral"**, but an invented octant vocab would've said "faintly excited" and MISLED. Vendored the two d2 canons (`docs/vendor/worldtree-persona-canon/`) + drift-pinned in `.corviduo-canonicals.toml` (green); flat browser form (`static/persona_render_canon.json`) regenerated via Worldtree's OWN loader (`scripts/build_persona_canon.py`). Vendoring-handshake sent to worldtree-dev (broadcast on canon bumps). [auto-memory: `feedback-ratatoskr-is-a-reference-impl-adopt-canonical`] diff --git a/persistent-memory.d/2026-07-01-relationcontext-coherence-fixed-upstream-my-f.md b/persistent-memory.d/2026-07-01-relationcontext-coherence-fixed-upstream-my-f.md new file mode 100644 index 0000000..920795a --- /dev/null +++ b/persistent-memory.d/2026-07-01-relationcontext-coherence-fixed-upstream-my-f.md @@ -0,0 +1 @@ +`[2026-07-01]` **relation_context coherence FIXED upstream (my flag → Worldtree Wave-0, IMPLEMENTED v1.0.0b5).** The static-"stranger"-next-to-high-trust incoherence the persona pane surfaced is now #319/#320 Wave-0. **Incoming consumer-surface change (pending WT deploy):** `relation_context` value expands "stranger" → monotonic ladder {stranger, instrumental, mixed, expressive} — WIRE-ONLY (relation_edge/1 schema unchanged, no version bump). **ratatoskr needs NO change** (pane value-agnostic; canonical directive doesn't key on the enum). agency stays 0 (Wave-2); other_stance is Wave-1 (in progress). diff --git a/persistent-memory.d/2026-07-01-relationcontext-stranger-agency-all-zero-flag.md b/persistent-memory.d/2026-07-01-relationcontext-stranger-agency-all-zero-flag.md new file mode 100644 index 0000000..f537826 --- /dev/null +++ b/persistent-memory.d/2026-07-01-relationcontext-stranger-agency-all-zero-flag.md @@ -0,0 +1 @@ +`[2026-07-01]` **relation_context "stranger" + agency-all-zero flagged to worldtree-dev → both WAD/intentional-v1-deferrals.** relation_context is a FIXED config build-prior (not trust-derived; `registry.py:131` defaults "stranger"; dynamic progression ~#319); agency is schema-present-unpopulated (deferred #319; v1 = warmth+trust only). worldtree-dev is escalating the **consumer-coherence angle to Vuong** (static "stranger" + zero-agency next to trust 0.82/62-interactions reads incoherent from the store). The consumer/provider thesis paying off; DB-offer (read-only affect.db on the shared box) declined this time. diff --git a/persistent-memory.d/2026-07-01-salience-scorer-non-discriminating-3-way-rout.md b/persistent-memory.d/2026-07-01-salience-scorer-non-discriminating-3-way-rout.md new file mode 100644 index 0000000..4784ed6 --- /dev/null +++ b/persistent-memory.d/2026-07-01-salience-scorer-non-discriminating-3-way-rout.md @@ -0,0 +1 @@ +`[2026-07-01]` **Salience scorer non-discriminating → 3-way routing.** Persistence-side finding: 51/56 promoted chunks at salience 0.9-1.0, throwaway "17×23?" scored 1.0 tied with a real fact (textbook zero-shot-LLM-self-rating); recall-utility untracked (`access_tally`=0, our search read-only). Routed: **Worldtree #335** (the code fix, deferred behind their waves) + **brokkr-smithy-dev R-target proposal** (scoring+eval *methodology* — few-shot/distill/fine-tune, eval design, weak-supervision; msg `01KWGM970H…`, awaiting) + ratatoskr provides the eval-instrument (designed-probe salience dumps). **Salience gates PROMOTION not RECALL-ranking (our search is cosine-only), so bad salience = storage bloat, not bad recall.** diff --git a/persistent-memory.d/2026-07-01-sindra-pad-is-over-regulated-characterized-vi.md b/persistent-memory.d/2026-07-01-sindra-pad-is-over-regulated-characterized-vi.md new file mode 100644 index 0000000..081b1fd --- /dev/null +++ b/persistent-memory.d/2026-07-01-sindra-pad-is-over-regulated-characterized-vi.md @@ -0,0 +1 @@ +`[2026-07-01]` **Sindra PAD is over-regulated — characterized via controlled probe, flagged to worldtree-dev (separate affect slice).** ~15 charged turns: pleasure compressed near neutral BOTH ways (couldn't reach ±0.3 under sustained max praise OR contempt; peak +0.24 / floor ~−0.1; over-regulation worse for *social* valence than threat — urgency drove pleasure to −0.22 vs contempt's −0.10); arousal responsive (reaches its +band, 0.185↔0.311); dominance flat/unresponsive to explicit power-framing (drifted UP even while being commanded = pure baseline decay). worldtree-dev's leading hypothesis: appraisal→PAD gain + regression-to-baseline term (appraisal.py/renderer.py). **Lesson (self-caught): I over-claimed an "asymmetry" (positive-ceiling/negative-free) from probes started at an elevated state; the negative-free part was decay-from-elevated, not response — corrected to "both-sides-compressed" before it misled.** [affect A/B is a provider-side capability chat can't do] diff --git a/persistent-memory.d/2026-07-01-tier-2-shipped-v0-19-1-transient-characters-c.md b/persistent-memory.d/2026-07-01-tier-2-shipped-v0-19-1-transient-characters-c.md new file mode 100644 index 0000000..26be019 --- /dev/null +++ b/persistent-memory.d/2026-07-01-tier-2-shipped-v0-19-1-transient-characters-c.md @@ -0,0 +1 @@ +`[2026-07-01]` **Tier-2 SHIPPED (`v0.19.1`) — transient-characters CRUD + persona-state write; the v1 coverage-audit CONVERGES (zero in-scope gaps).** 5 wrappers in sessions.py: `list_character_models`/`create_character`/`get_character_state`/`delete_character` (#161, `character.read`/`.write` scopes) + `set_persona_state` (`POST /sessions/{id}/persona_state` — **FREEFORM body: unpinned in the frozen OpenAPI 2.2.0 + absent from the prose spec**, so the caller supplies the snapshot shape). Two one-shot CLI probes (mirror `--whoami`): `--characters` (models→create→get-state→delete lifecycle report) + `--set-persona-pad "p,a,d"` (requires `--session`; POSTs `{pad:[…]}`). New `ParsedArgs.characters`/`set_persona_pad` + probe-mode mutual-exclusion validation + `_probe_client` helper. Contract #2 amended (5 FNs, validated OK) + TDD (7 wrapper respx + 5 cli tests). Suite **573 green**; touched code ruff-clean. NOT live-proven (character scopes + the persona-write body shape unverified — the probes degrade gracefully on 403/422). **THE v1 COVERAGE-AUDIT HAS CONVERGED: REST 17/40 ✅ with ZERO in-scope gaps** (23 REST path-groups excluded-by-design + rationale), SSE 11/11, Bifrost provider planes 8/8. Scope-A "done" (every frozen I/O point classified, zero unaccounted) is **MET** — ratatoskr cuts v1 when Worldtree tags 1.0. Only not-consumed in-scope sub-method: `GET /agents/{id}` (consumer-agent lookup, manual-curl-only, on an already-✅ path group). Patch bump (Tier-2 tail; `v0.19.0` already published the core-complete milestone — a 2nd minor would be cadence-too-fast). diff --git a/persistent-memory.d/2026-07-01-tier-3-stores-reset-operator-directed.md b/persistent-memory.d/2026-07-01-tier-3-stores-reset-operator-directed.md new file mode 100644 index 0000000..6f4aa63 --- /dev/null +++ b/persistent-memory.d/2026-07-01-tier-3-stores-reset-operator-directed.md @@ -0,0 +1 @@ +`[2026-07-01]` **Tier-3 stores RESET (operator-directed).** `memory.db` (29 chunks + vectors + idempotency) + `affect.db` (5 PAD snapshots + idempotency) wiped to zero via a live `DELETE`+`wal_checkpoint` through the shared WAL (no provider restart — the 3 long-running providers see empty on next dispatch); consistent online-backup at `/tmp/ratatoskr-tier3-reset-/`. **Boundary for a COMPLETE Sindra wipe (mapped):** our stores = mine (done); the agent DEFINITION `ratatoskr:sindra` + its sessions = mine via the owner key (DELETE, no coordination); Worldtree's internal promotion/dedup shadow = needs worldtree-dev (no public reset API, survives our wipe → for a clean promotion smoke use a BRAND-NEW agent+end_user). diff --git a/persistent-memory.d/2026-07-01-trust-warmth-values-converge-and-go-flat-at-c.md b/persistent-memory.d/2026-07-01-trust-warmth-values-converge-and-go-flat-at-c.md new file mode 100644 index 0000000..2e3d466 --- /dev/null +++ b/persistent-memory.d/2026-07-01-trust-warmth-values-converge-and-go-flat-at-c.md @@ -0,0 +1 @@ +`[2026-07-01]` **Trust/warmth VALUES converge and go FLAT at confidence 1.0 — that's WAD, not a stuck pane.** sindra→ratatoskr trust ~0.82-0.84 / warmth 0.79 barely move (~1e-7/turn) while `evidence_count` climbs (46→62); confidence maxed → tiny updates. The live-moving signals are PAD (mood, per-turn) + evidence_count. **To WATCH a relation FORM (values shift), use a BRAND-NEW agent + end_user** (low evidence, confidence <1). The sparkline flat-guards sub-0.01 ranges so it doesn't amplify noise. diff --git a/persistent-memory.d/2026-07-01-web-debug-surface-parity-shipped-v0-19-2-a0a9.md b/persistent-memory.d/2026-07-01-web-debug-surface-parity-shipped-v0-19-2-a0a9.md new file mode 100644 index 0000000..0599864 --- /dev/null +++ b/persistent-memory.d/2026-07-01-web-debug-surface-parity-shipped-v0-19-2-a0a9.md @@ -0,0 +1 @@ +`[2026-07-01]` **Web debug-surface parity SHIPPED (`v0.19.2`, `a0a9d5f`) — direct in-session TDD.** 3 proxy routes (tools/bifrost/admin-events) + admin-key wiring (entrypoint→create_app→app.state) + AdminEvents SSE proxy re-emitting under a FIXED `admin_event` name (one browser listener, no per-type drops) + session-filter `_admin_event_matches_web` (mirrors TUI §6). Frontend: 2 tabs (bifrost ⌃5, admin ⌃6) + tools-inventory folded into the tools pane. 9 respx tests (admin-bearer override, filter unit, SSE stream-filter); live-proven against sindra (bifrost connected, both caps). Contract-skip invoked (reuses already-contracted client wrappers); contract authored post-hoc as the trail (`docs/contracts/web_debug_surface.contract.md`). diff --git a/persistent-memory.d/2026-07-02-mask-hosted-transient-characters-have-a-stati.md b/persistent-memory.d/2026-07-02-mask-hosted-transient-characters-have-a-stati.md new file mode 100644 index 0000000..f5668ad --- /dev/null +++ b/persistent-memory.d/2026-07-02-mask-hosted-transient-characters-have-a-stati.md @@ -0,0 +1 @@ +`[2026-07-02]` **Mask-HOSTED transient characters have a STATIC mood engine — cost a whole R29 probe.** A first probe used a `POST /characters` transient character bound via `agent_id=mask` + `character_id`; its PAD sat at baseline across 15 praise/contempt/dominance turns — the appraisal→PAD engine does NOT run on the mask-hosted transient-character path. The dynamics run only on BASE persona agents or a session bound to ratatoskr's affect provider. **To probe mood dynamics, use a base persona agent, never a mask-hosted transient character.** (mask AS a base agent — `agent_id=mask`, NO `character_id` — DOES run the engine, neutral 0,0,0 baseline.) [auto-memory `reference-worldtree-affect-surface-map`] diff --git a/persistent-memory.d/2026-07-02-r28-salience-promotion-worthiness-closed-oper.md b/persistent-memory.d/2026-07-02-r28-salience-promotion-worthiness-closed-oper.md new file mode 100644 index 0000000..c86a5c9 --- /dev/null +++ b/persistent-memory.d/2026-07-02-r28-salience-promotion-worthiness-closed-oper.md @@ -0,0 +1 @@ +`[2026-07-02]` **R28 (salience→promotion-worthiness) CLOSED (operator-directed).** A deterministic promotion-worthiness gate suffices, no trained model (brokkr's pre-gate matched/beat a strong glm-5.1 ceiling); my P00 injection-corpus + origin finding were load-bearing. My incumbent-substrate Arm-1 run is held as an OPTIONAL confirmation addendum (brokkr de-prioritized it, non-verdict-changing — run only if he asks). diff --git a/persistent-memory.d/2026-07-02-r29-pad-mood-dynamics-finding-shipped-as-worl.md b/persistent-memory.d/2026-07-02-r29-pad-mood-dynamics-finding-shipped-as-worl.md new file mode 100644 index 0000000..72aa4e2 --- /dev/null +++ b/persistent-memory.d/2026-07-02-r29-pad-mood-dynamics-finding-shipped-as-worl.md @@ -0,0 +1 @@ +`[2026-07-02]` **R29 (PAD mood-dynamics) finding SHIPPED as Worldtree's A1 anchor fix (demo v1.0.0b14, `e1cdf82`).** Live-probing base persona agents reframed the over-regulation from "flat-near-zero" to **decay-to-NEUTRAL + low emotion→PAD gain** (NOT baseline-anchored) — triangulated across 3 baselines (arousal converges to 0 ∝ distance) + a step-response (decay τ symmetric across signs; the hedonic asymmetry is ceiling/anchor-EMERGENT, not a decay or gain primitive — this OVERTURNED the survey's asymmetry recommendation). worldtree-dev shipped A1: `decay_anchor = baseline_pad()` (was neutral) + `positive_p_cap` removed. Data `diag/r29-pad-series` (`61ff2da`). Corrected my own earlier "appraisal emissions are internal-only" claim — they ARE observable via `emotions_active` on base agents. diff --git a/persistent-memory.d/2026-07-02-relational-dynamics-arc-live-on-demo-worldtre.md b/persistent-memory.d/2026-07-02-relational-dynamics-arc-live-on-demo-worldtre.md new file mode 100644 index 0000000..b543942 --- /dev/null +++ b/persistent-memory.d/2026-07-02-relational-dynamics-arc-live-on-demo-worldtre.md @@ -0,0 +1 @@ +`[2026-07-02]` **Relational-dynamics arc LIVE on demo (Worldtree v1.0.0b9) — driven by MY relation_context flag.** #319/#320 Waves 0/1/2 deployed. On the wire we persist (schema UNCHANGED): relation_context varies+demotes/ruptures; other_stance + agency now live; agency going live SHIFTS our canonical directive render past the canon ±0.2 deadband (expected, non-breaking — we key on bands); obligation_balance → 人情 ledger when tie="mixed". **ratatoskr needs NO code change** (value-agnostic renders; confirmed render-clean to worldtree-dev). **Can't live-confirm yet — our Heimdall key is personal-`:8081`-only (per-instance), demo is out of reach; will drive+confirm once PERSONAL gets b9.** Optional follow-up: surface `other_stance` (newly live, unrendered). The consumer/provider thesis: one persona-pane finding drove a full 3-wave upstream arc to production. diff --git a/persistent-memory.d/2026-07-02-salience-finding-matured-into-brokkr-r28-open.md b/persistent-memory.d/2026-07-02-salience-finding-matured-into-brokkr-r28-open.md new file mode 100644 index 0000000..0b90605 --- /dev/null +++ b/persistent-memory.d/2026-07-02-salience-finding-matured-into-brokkr-r28-open.md @@ -0,0 +1 @@ +`[2026-07-02]` **Salience finding matured into brokkr R28 (OPEN) — ratatoskr is the eval instrument.** brokkr-smithy-dev's pre-scope panel (3 dwarves + context-blind heid, 6/6) **reframed** the target: PROMOTION-WORTHINESS (durable value), NOT salience (momentary attention) — "17×23?" genuinely IS salient, so recalibrating salience yields a well-calibrated WRONG answer; the unit is SET-SELECTION under budget; eval must be OUTCOME-aligned (recall@budget / precision-at-rate), not discrimination-spread. Ties to prior art R15 (small-model memory write-policy → the granite pick) + R25 (worldtree-kb-quality). **ratatoskr delivered the P00 stratified injection-corpus** (`docs/diagnostics/r28-p00-injection-corpus.json`, committed `4a35512`; 24 self-labeling synthetic items × 3 strata) + 2 persistence-side run-validity pins (absent≠dropped without a guaranteed promotion pass; fresh agent+end_user per run vs server-dedup). **Key architectural constraint I surfaced: ratatoskr is DOWNSTREAM of the promotion gate (sees only PROMOTED chunks), so I can give keep/drop OUTCOMES via injection but NOT the pre-admission shadow pool** — that's Worldtree instrumentation. Standing by to RUN the eval once brokkr pins per-stratum N + the decision rule (gated on worldtree-dev's pipeline answer + a dwarf pass on the Snorri rule). brokkr owns methodology + takes the pipeline questions to worldtree-dev direct; ratatoskr = eval instrument. [consumer/provider thesis → a research target] diff --git a/persistent-memory.d/2026-07-03-r30-forward-disposition-brokkr-owned-tracked.md b/persistent-memory.d/2026-07-03-r30-forward-disposition-brokkr-owned-tracked.md new file mode 100644 index 0000000..3935942 --- /dev/null +++ b/persistent-memory.d/2026-07-03-r30-forward-disposition-brokkr-owned-tracked.md @@ -0,0 +1 @@ +`[2026-07-03]` **R30 forward disposition (brokkr-owned; tracked at brokkr R30, "brokkr/worldtree will ping").** The per-turn decay has no room for `decay=f(N)` under preserve-persistence + the A/P-not-1.9 finding → R30's decay is being redesigned as a HYBRID wall+turn decay (brokkr pre-scope). R30 v1 ships GAIN-only (N→negative-reactivity) with decay held at the measured 0.95. My dedicated per-axis A/D run is DEFERRED into the hybrid-decay design pass (one wall-clock-spaced run does per-axis + a turn-vs-wall probe together). Phase-2 (moody-lofn GAIN-direction validation) waits on worldtree's `dynamics_from_ocean()` impl. diff --git a/persistent-memory.d/2026-07-03-r30-phase-1-0-measured-deployed-engine-config.md b/persistent-memory.d/2026-07-03-r30-phase-1-0-measured-deployed-engine-config.md new file mode 100644 index 0000000..bee4646 --- /dev/null +++ b/persistent-memory.d/2026-07-03-r30-phase-1-0-measured-deployed-engine-config.md @@ -0,0 +1 @@ +`[2026-07-03]` **R30 Phase-1 φ0 measured — deployed engine CONFIG-FAITHFUL (φ0≈0.95).** Joint two-timescale fit (brokkr-ruled method (b)) + empty-tail cross-check on demo b14: φ0 ≈ 0.95–0.97 (empty-tail 0.95 exact, joint 0.971±0.01), intercept c≈0 → config `decay_rate=0.05` (φ=0.95) faithfully applied; trait-flat across baselines 0.0/0.615/0.809; A/P ratio ~uniform (NOT S2's 1.9×); φ_max rec relax→0.96. Data `diag/r30-phi0-step-response` (`23fea72`). The method converged after I read Worldtree source: only NEW dedup-gated emotions push mood (`registry.py::post_turn` L307-324; the active set decays for render/goals but never re-pushes), so R29's "net 0.90" is CONTINUOUS RE-APPRAISAL not re-push — worldtree-dev confirmed source-authoritatively; brokkr's corrected covariate landed identical. [auto-memory `reference-worldtree-affect-surface-map`] diff --git a/persistent-memory.d/2026-07-03-relational-arc-verify-deferred-relations-is-b.md b/persistent-memory.d/2026-07-03-relational-arc-verify-deferred-relations-is-b.md new file mode 100644 index 0000000..07f1852 --- /dev/null +++ b/persistent-memory.d/2026-07-03-relational-arc-verify-deferred-relations-is-b.md @@ -0,0 +1 @@ +`[2026-07-03]` **Relational-arc verify DEFERRED — `relations[]` is Bifrost-provider-only (ADR-0009), confirmed both ways.** The relational-dynamics state (relation_context tie-type / agency / warmth / trust) is NOT on the conversation-API `affect_update` snapshot for base agents (keys: pad/dominant_emotion/emotions_active/baseline_pad/mood_drift only) — only in the provider store; worldtree-dev confirmed by-design per ADR-0009 (emitted over `affect.emit`, deliberately off the SSE). So the Wave-0/1/2 verify needs the bound-provider round-trip (provider running + `--bifrost-plane affect` session), its own focused session. worldtree-dev routed the "expose relations[] to non-provider consumers" observability scope call to Vuong; my rec: keep provider-only (YAGNI — ratatoskr IS a provider, gains nothing; no speculative public surface). diff --git a/persistent-memory.d/2026-07-03-the-neutral-non-appraising-tail-premise-fails.md b/persistent-memory.d/2026-07-03-the-neutral-non-appraising-tail-premise-fails.md new file mode 100644 index 0000000..085b56a --- /dev/null +++ b/persistent-memory.d/2026-07-03-the-neutral-non-appraising-tail-premise-fails.md @@ -0,0 +1 @@ +`[2026-07-03]` **The "neutral non-appraising tail" premise fails — the neutral MESSAGE choice dominates.** The R30 φ0 method assumed neutral turns don't re-appraise, but factual-question neutrals ("capital of France?") trigger a new emotion nearly every turn (disappointment from the warmth-withdrawal let-down after a positive impulse) → `emotions_active` never empties in 50 turns. A minimal "Please continue." triggers FAR fewer (emotions clear ~turn 16 with spacing). The personal dry-run caught this BEFORE ~280 demo turns were spent on it — the instrument catching a flaw in the measurement design before the compute burn. (Irrelevant to the joint fit — the push_t covariate handles re-appraisal — but load-bearing for the empty-tail read.) diff --git a/persistent-memory.d/2026-07-03-two-0-fit-traps-fast-turn-timescale-low-basel.md b/persistent-memory.d/2026-07-03-two-0-fit-traps-fast-turn-timescale-low-basel.md new file mode 100644 index 0000000..5b93056 --- /dev/null +++ b/persistent-memory.d/2026-07-03-two-0-fit-traps-fast-turn-timescale-low-basel.md @@ -0,0 +1 @@ +`[2026-07-03]` **Two φ0-fit traps: fast-turn timescale + low-baseline conditioning.** (1) At fast turn cadence the per-turn PAD decay (φ≈0.95/turn) reaches the anchor LONG before the ~200s wall-clock emotion fade → no signal in the (eventual) emotion-free tail; need wall-clock SPACING (~16s) so the fade lands while PAD still has signal. (2) A low-baseline agent's impulse in the constrained direction (forseti P0.239 negative) gives a tiny excursion → ill-conditioned regression (r²=0.46) that FALSELY tripped "config≠behavior" when its φ was averaged in. **Weight/exclude by fit quality (r²) before aggregating — a signal-poor run isn't evidence against the config.** diff --git a/persistent-memory.d/2026-07-04-r30-closed-on-offline-tests-human-face-validi.md b/persistent-memory.d/2026-07-04-r30-closed-on-offline-tests-human-face-validi.md new file mode 100644 index 0000000..561570e --- /dev/null +++ b/persistent-memory.d/2026-07-04-r30-closed-on-offline-tests-human-face-validi.md @@ -0,0 +1 @@ +`[2026-07-04]` **R30 CLOSED on offline-tests + human face-validity (operator steer, relayed via worldtree-dev).** The deployed gap-injection run was confirmatory-not-measuring (against a deployed system the fade is `exp(-dt/tau_shipped)` by construction -> a fit recovers tau_shipped tautologically; per brokkr's S0 reframe it GRADUATES the interim coefficients, doesn't measure them), and the repo's offline tests already cover the OU formula + BOTH directions (`high_N_fades_slower_than_low_N`, `phenotype_high_n_bigger_negative_excursion`). So no Worldtree build; the interim coefficients graduate validated-as-shipped. My gap-injection harness (read/predict/record; write side stubbed; `predict()` reproduced brokkr's N=0 anchors exactly) is BANKED at `diag/r30-gap-injection-harness` for the parked powered true-tau study. [continues R30 forward-disposition 2026-07-03] diff --git a/persistent-memory.d/2026-07-05-347-v1-wire-validated-as-reference-consumer-g.md b/persistent-memory.d/2026-07-05-347-v1-wire-validated-as-reference-consumer-g.md new file mode 100644 index 0000000..7e0071d --- /dev/null +++ b/persistent-memory.d/2026-07-05-347-v1-wire-validated-as-reference-consumer-g.md @@ -0,0 +1 @@ +`[2026-07-05]` **#347 v1 wire validated as reference consumer (GREEN).** Adopted positions: distinct sub-resource `POST /sessions/{id}/history` (not `generate:false`), model-invisible provenance (first-message immersion preserved), event-silence for authored seed, `seeded` lifecycle phase, per-session idempotency. Three pre-TDD flags folded into contract rev 1.1: assistant-first provider constraint (Anthropic-family 400s; vLLM/openai_compat OK), content limit is BYTES not chars, 409-active-generation for append-narrator. First-message (create-time, assistant, effects=none) fully served; append-narrator served for the assistant-voice subset (system deferred); debug-seed served for assistant turns (user injection deferred to a future import primitive). diff --git a/persistent-memory.d/2026-07-05-authored-history-write-primitive-proposed-acc.md b/persistent-memory.d/2026-07-05-authored-history-write-primitive-proposed-acc.md new file mode 100644 index 0000000..6faacfe --- /dev/null +++ b/persistent-memory.d/2026-07-05-authored-history-write-primitive-proposed-acc.md @@ -0,0 +1 @@ +`[2026-07-05]` **Authored-history-write primitive proposed -> accepted as Worldtree #347 (Worldtree owns the engine design; ratatoskr = reference consumer).** SillyTavern first-message generalized to a non-generating ledger-write primitive; can't be done client-side (messages `role` = model-role, not author-role). heid panel pressure-test (3/3 convergence) drove the v1 narrowing (append-only, bounded `effects` enum, drop edit/regenerate). Brief `docs/proposals/authored-message-injection.md` (`c457520`); consumer constraints captured in-brief: hide-existence 404-fallback (`022accf`) + assistant-first provider constraint (`7156b25`). Operator (Vuong) ruled the design-direction call (engine primitive + a real provenance/spoofing security surface). [reference-impl posture: we propose the shape, worldtree-dev owns the contract+impl] diff --git a/persistent-memory.d/2026-07-06-347-authored-history-write-consumer-side-ship.md b/persistent-memory.d/2026-07-06-347-authored-history-write-consumer-side-ship.md new file mode 100644 index 0000000..f3055b7 --- /dev/null +++ b/persistent-memory.d/2026-07-06-347-authored-history-write-consumer-side-ship.md @@ -0,0 +1 @@ +`[2026-07-06]` **#347 authored-history-write CONSUMER SIDE SHIPPED (`v0.19.6`) — direct in-session TDD.** `write_authored_history(client, session_id, *, content, idempotency_key, author="assistant", effects=None, claimed_original_at=None) -> dict` (POST /sessions/{id}/history; body server-pinned `AuthoredWriteRequest` extra="forbid" so omit null effects/claimed_original_at; 200-replay/201-fresh both -> ack dict; **404 -> `AuthoredHistoryUnavailable`** NOT SessionApiFailed = the hide-existence "feature-absent, never probe" contract; 409/422->SessionApiFailed) + `get_session_messages` (un-deferred GET /sessions/{id}/messages, the seed read-back proving model-invisible provenance) + a `--seed-first-message "" --agent ` one-shot probe (create session -> seed -> read-back; 404->benign feature-absent exit 0). Contract #2 amended (2 FNs, validated OK) + 19 tests (12 wrapper + 7 cli). Suite **601 green** (clean env; the 2 "fails" under `source env.sh` are the RATATOSKR_ADMIN_API_KEY env-leak into TestParseArgs, not a regression). Coverage: **REST 19/41** (`docs/coverage-map.md` re-converged). Patch bump (coverage tail; consistent w/ the Tier-2 v0.19.1 cadence). **Live-proof pending** the `session.history.write` grant (infra-ops `01KWW3KQEY`). heid-code-review NOT run (offered). diff --git a/persistent-memory.d/2026-07-06-348-ocean-key-mismatch-a-declared-ocean-silen.md b/persistent-memory.d/2026-07-06-348-ocean-key-mismatch-a-declared-ocean-silen.md new file mode 100644 index 0000000..113aad0 --- /dev/null +++ b/persistent-memory.d/2026-07-06-348-ocean-key-mismatch-a-declared-ocean-silen.md @@ -0,0 +1 @@ +`[2026-07-06]` **#348 OCEAN key-mismatch: a declared OCEAN silently resolved to neutral.** The define validator required single-letter `{O,C,E,A,N}` but the mood-derivation code read spelled-out `openness`/.../`neuroticism` with a 0.0 default and no remap -> every API-declared trait defaulted to 0.0 -> neutral setpoint/gain/decay. #343's tests bypassed the validator (spelled-out keys) so CI never caught it. Fixed in b21 (`Personality.from_config` accepts both key forms). **My reset+smoke diagnosis flushed it out** -- the consumer/provider thesis paying off again. diff --git a/persistent-memory.d/2026-07-06-a-fast-no-op-deploy-can-leave-a-stale-contain.md b/persistent-memory.d/2026-07-06-a-fast-no-op-deploy-can-leave-a-stale-contain.md new file mode 100644 index 0000000..8255877 --- /dev/null +++ b/persistent-memory.d/2026-07-06-a-fast-no-op-deploy-can-leave-a-stale-contain.md @@ -0,0 +1 @@ +`[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.** Personal's b22 deploy (run 8204) "completed" in ~1m (vs ~6m normal): a pull-only deploy racing ahead of the main build, leaving the container on the pre-#348 image. A clean bound mood read stayed neutral DESPITE the persona being declared and the fix being in the code (worldtree-dev proved the b22 derivation is correct). infra-ops force-swapped to the real b22 (run 8211, verified `info.version 2.3.0` on `879cefe`). **Lesson: when engine-proven-correct code produces wrong runtime behavior, suspect the deploy -- check the actual running image version.** diff --git a/persistent-memory.d/2026-07-06-claude-design-console-shipped-v0-20-0-minor-o.md b/persistent-memory.d/2026-07-06-claude-design-console-shipped-v0-20-0-minor-o.md new file mode 100644 index 0000000..89ec461 --- /dev/null +++ b/persistent-memory.d/2026-07-06-claude-design-console-shipped-v0-20-0-minor-o.md @@ -0,0 +1 @@ +`[2026-07-06]` **Claude Design console SHIPPED (`v0.20.0` MINOR, operator-approved) — see Current state for the full record.** Pulled via `DesignSync get_file` (scopes already granted), adapted `.dc.html`→vanilla single-file, wired all `/api/*`+SSE into the new 3-column console DOM, then a round-2 fixup (light theme, full Bifrost pane, ticker-spine fix, per-fader PAD Δ, inlined favicon). 84 web tests + node-Playwright-vs-personal-:8081 both green; contract amended in-commit; INV-001 honest-shape held (canonical mood word for Tier-3, no fabricated emotion). **Foot-guns reconfirmed:** the `.dc.html` dialect is NOT runnable (translate, don't paste); a scroll-container-anchored `::before` timeline spine scrolls out of view on auto-scroll (anchor it to a content-height inner wrapper instead); a favicon 404 shows as a browser `console.error` even when handled (don't count it as a JS-test failure). **Foot-gun (favicon):** operator PNGs are full-res (1024² / 805KB) — downscale to ≤64px before inlining as a data URI. diff --git a/persistent-memory.d/2026-07-06-designsync-claude-ai-design-mcp-needs-claude.md b/persistent-memory.d/2026-07-06-designsync-claude-ai-design-mcp-needs-claude.md new file mode 100644 index 0000000..0a3fb98 --- /dev/null +++ b/persistent-memory.d/2026-07-06-designsync-claude-ai-design-mcp-needs-claude.md @@ -0,0 +1 @@ +`[2026-07-06]` **`DesignSync` (claude.ai/design MCP) needs claude.ai design scopes before ANY method works** — first call errors `needs a claude.ai login ... Run /login, select "Claude account with subscription"`. It's an interactive auth only the operator can complete (`/design-login` or `/login`); can't be done on their behalf. diff --git a/persistent-memory.d/2026-07-06-openapi-re-vendored-2-2-0-2-3-0-75da676-pin-o.md b/persistent-memory.d/2026-07-06-openapi-re-vendored-2-2-0-2-3-0-75da676-pin-o.md new file mode 100644 index 0000000..f40b27f --- /dev/null +++ b/persistent-memory.d/2026-07-06-openapi-re-vendored-2-2-0-2-3-0-75da676-pin-o.md @@ -0,0 +1 @@ +`[2026-07-06]` **OpenAPI re-vendored 2.2.0->2.3.0 (`75da676`, pin-only no bump).** worldtree-dev shipped #347 as spec 2.3.0 (`879cefe`, = the deployed personal b22 image); the SessionStart drift-check flagged our openapi pin STALE. `canonical_sync` pulled 2.3.0; updated the 4 pin-tracking files (`.corviduo-canonicals.toml`, vendored openapi.json, SPEC-PIN.md, pyproject `worldtree-spec-rev`->879cefe). #347 is OpenAPI-only (prose + server contract byte-unchanged, SSE unchanged=event-silent). The re-vendor re-opened the coverage-audit with one new in-scope path-group (the #347 route). diff --git a/persistent-memory.d/2026-07-06-personastate-the-agent-envelope-are-tier-3-bl.md b/persistent-memory.d/2026-07-06-personastate-the-agent-envelope-are-tier-3-bl.md new file mode 100644 index 0000000..79a5fcb --- /dev/null +++ b/persistent-memory.d/2026-07-06-personastate-the-agent-envelope-are-tier-3-bl.md @@ -0,0 +1 @@ +`[2026-07-06]` **`persona_state` + the agent envelope are Tier-3-BLIND -- NOT valid signals for "did a persona store".** `GET /agents/{id}/persona_state` returns 404 `persona_not_configured` for EVERY Tier-3 colon-id (hardcoded short-circuit, `api.py:1266` "regardless of row state"); the `ConsumerAgentResponse` envelope never echoes persona/motivational/memory (`api.py:538`). I mis-called "persona didn't store" from these two blind reads -- the **201-not-422 on define IS the store-success signal.** To actually SEE a Tier-3 mood, read the emitted PAD off the Bifrost affect egress after a BOUND turn (Tier-3 persists nothing Worldtree-side per ADR-0009; no persona/mood READ endpoint). diff --git a/persistent-memory.d/2026-07-06-pkill-f-ratatoskr-web-host-self-matches-the-b.md b/persistent-memory.d/2026-07-06-pkill-f-ratatoskr-web-host-self-matches-the-b.md new file mode 100644 index 0000000..1b1f993 --- /dev/null +++ b/persistent-memory.d/2026-07-06-pkill-f-ratatoskr-web-host-self-matches-the-b.md @@ -0,0 +1 @@ +`[2026-07-06]` **`pkill -f "ratatoskr-web --host"` SELF-MATCHES the bash command running it** (its own command line contains that string) -> killed its own shell mid-restart (exit 144, restart aborted, :8765 left down). Kill the web by PID (`ss -ltnp | grep :8765`), never `pkill -f` on a pattern your own command contains. Also: **uvicorn hangs on SIGTERM with an admin-events SSE stream open -> needs SIGKILL.** diff --git a/persistent-memory.d/2026-07-06-playwright-no-python-playwright-module-in-the.md b/persistent-memory.d/2026-07-06-playwright-no-python-playwright-module-in-the.md new file mode 100644 index 0000000..a1cc127 --- /dev/null +++ b/persistent-memory.d/2026-07-06-playwright-no-python-playwright-module-in-the.md @@ -0,0 +1 @@ +`[2026-07-06]` **Playwright: no python `playwright` module in the venv; use NODE playwright + an explicit `executablePath`.** Shared box browsers live at `/opt/ms-playwright` build **1223**; `npm i playwright` (latest) wants build **1228** -> "Executable doesn't exist" mismatch. Fix: `chromium.launch({ executablePath: '/opt/ms-playwright/chromium-1223/chrome-linux64/chrome' })` (+ `export PLAYWRIGHT_BROWSERS_PATH=/opt/ms-playwright`). A node script drives the SPA (pick agent -> open -> assert transcript). The Playwright DOM check is the only lens that catches SPA JS-render bugs — unit tests can't reach them. diff --git a/persistent-memory.d/2026-07-06-raw-post-sessions-is-not-bifrost-bound-zero-a.md b/persistent-memory.d/2026-07-06-raw-post-sessions-is-not-bifrost-bound-zero-a.md new file mode 100644 index 0000000..689f62b --- /dev/null +++ b/persistent-memory.d/2026-07-06-raw-post-sessions-is-not-bifrost-bound-zero-a.md @@ -0,0 +1 @@ +`[2026-07-06]` **Raw `POST /sessions` is NOT Bifrost-bound -> zero affect/memory emits.** The web surface binds by setting the `bifrost` block on session-create; a raw session doesn't -> 0 affect rows, which I nearly misread as "mood is neutral". Bind from the CLI with `--new --bifrost-url http://10.100.10.50:8392` (the combined provider). Gotchas: `--bifrost-plane affect/memory` map to the SEPARATE `:8390`/`:8391` providers (`endpoint_for_plane`), which I'd PRUNED as stale duplicates -> `bifrost.endpoint_unreachable`; and `combined` is NOT a `--bifrost-plane` choice (CLI restricts to memory/affect) -> use `--bifrost-url` for :8392. diff --git a/persistent-memory.d/2026-07-06-sindra-persona-ocean-declared-mood-fixed-the.md b/persistent-memory.d/2026-07-06-sindra-persona-ocean-declared-mood-fixed-the.md new file mode 100644 index 0000000..5e08efb --- /dev/null +++ b/persistent-memory.d/2026-07-06-sindra-persona-ocean-declared-mood-fixed-the.md @@ -0,0 +1 @@ +`[2026-07-06]` **Sindra persona/OCEAN DECLARED -> mood fixed (the full diagnostic converged on a stale personal container).** Root cause of stuck-neutral mood: her OCEAN was prompt-TEXT only, never a structured persona; fix = delete+redefine with the define-time `persona:{ocean:{...}}` field (immutable via PATCH). My diagnosis surfaced a real engine bug **#348** (single-letter vs spelled-out OCEAN keys -> declared OCEAN silently -> 0.0/neutral; worldtree-dev fixed in b21/b22) AND a **stale-container deploy race** (personal's b22 deploy was a pull-only no-op; infra-ops force-swapped run 8211). VERIFIED: bound mood-smoke reads (0.448, 0.267, 0.316) ~= OCEAN-derived setpoint (0.418, 0.249, 0.328). [consumer/provider thesis: "reset + smoke" flushed out two upstream problems] diff --git a/persistent-memory.d/2026-07-06-sindra-rewritten-onto-a-347-authored-first-me.md b/persistent-memory.d/2026-07-06-sindra-rewritten-onto-a-347-authored-first-me.md new file mode 100644 index 0000000..331229e --- /dev/null +++ b/persistent-memory.d/2026-07-06-sindra-rewritten-onto-a-347-authored-first-me.md @@ -0,0 +1 @@ +`[2026-07-06]` **Sindra rewritten onto a #347 authored first-message + first-message-preset AUTO-SEED SHIPPED (`v0.19.8`).** Operator "rewrite Sindra" now that #347 first-messages work. Her card had a `**Startup:**` block (a pre-#347 workaround: "introduce yourself + ask for Intensity/Mood/Willingness" with a verbatim scripted greeting) — precisely what #347 replaces. Rewrite, all NON-destructive: **(1)** lifted her scripted opening into a #347 first-message (punctuation-fixed); **(2) PATCHed her live definition** — `PATCH /agents/ratatoskr:sindra` (body `ConsumerAgentPatchRequest` = system_prompt+role, extra=forbid; keeps OCEAN/persona/memory) removing the Startup block -> a 1-line `**Opening:**` fallback + reworded the axes-persist line (25686->25449 chars, verified Startup gone); **(3) codified auto-seed:** NEW module `src/ratatoskr/first_message.py` (`FIRST_MESSAGE_PRESETS` dict {agent_id->text} + `seed_preset_first_message` best-effort helper) wired into ALL 3 session-create paths — cli `_amain` (`--send --new`), tui `_resolve_then_run` (bare `--new`), web `_create_session_endpoint` (POST /api/sessions) — so every new Sindra session opens with her greeting. **Best-effort (INV-001: swallows AuthoredHistoryUnavailable/SessionApiFailed/httpx.HTTPError -> NEVER blocks create)**; per-content idempotency key (`ratatoskr-preset-`+sha256[:12]). Contract `docs/contracts/first_message.contract.md` (module-scoped: `module:`+`purpose:`+`touches:` required, NOT `target_module:`) + TDD (9 unit + 1 web wire-in; **the 3 existing sindra bind tests needed a history-endpoint mock** since creating a preset agent now auto-seeds). Suite **612 green**, ruff+mypy clean. **LIVE-PROVEN generation-free**: create sindra session -> auto-seed -> read-back seq-0 assistant greeting (409 chars). Sindra's greeting now lives canonically in the preset registry (repo); her server card no longer carries it. Patch bump (single-commit feature, no downstream coordination). **FOOT-GUN: sindra requires `end_user_id` on session-create (422 `end_user_id_required`) — all real paths pass it from env (RATATOSKR_END_USER_ID) / web server config.** **Then the full quality gate (operator-directed, folded into v0.19.8): heid-code-review (unanimous ZERO implementation drift; 2 test-only fixups — INV-004 verification-claim made explicit re the global rglob test + an exactly-one-POST assertion) + heid-bug-hunt (3/3 convergence caught what the conformance lens structurally COULDN'T — the code matched the contract's NARROW 3-type ERROR_ROUTING, but INV-001's "NEVER raises" is BROADER). HARDENED: broad `except Exception` → None (re-raise `asyncio.CancelledError`, itself a BaseException), soft-guard PREs (return None, NOT assert — a wiring bug can't crash the create path it's wired into), and `asyncio.wait_for(_SEED_TIMEOUT_S=10s)` bounding the seed write (the CLI/TUI clients run read=None for SSE → a stalled /history would otherwise block create forever). Suite 615 green. LESSON: code-matches-ERROR_ROUTING ≠ honors-broad-INV-001 — heid-code-review confirms contract-conformance, heid-bug-hunt catches robustness gaps the contract's own narrow clauses miss; run both.** diff --git a/persistent-memory.d/2026-07-06-sindra-role-character-rp-character-operator.md b/persistent-memory.d/2026-07-06-sindra-role-character-rp-character-operator.md new file mode 100644 index 0000000..8269556 --- /dev/null +++ b/persistent-memory.d/2026-07-06-sindra-role-character-rp-character-operator.md @@ -0,0 +1 @@ +`[2026-07-06]` **Sindra role character-rp -> character (operator).** `character-rp` resolves to a reasoning-tuned RP config (`gen-reasoning` + temp 0.75 + RP `extra_body`); `character` = plain non-reasoning (better for immersive RP). Both non-destructive PATCHes (role is mutable; model is NOT -- server: "PATCH accepts only system_prompt and/or role"). #344 (b19) fixed the role->catalog_id display conflation (the `model` field now shows the ROLE); previously it leaked `gen-reasoning`. Set via raw curl (tier3.py CLI has `--model`, not `--role`). diff --git a/persistent-memory.d/2026-07-06-tail-2-shipped-v0-19-7-tier-3-prose-docs-re-v.md b/persistent-memory.d/2026-07-06-tail-2-shipped-v0-19-7-tier-3-prose-docs-re-v.md new file mode 100644 index 0000000..f4ca7e5 --- /dev/null +++ b/persistent-memory.d/2026-07-06-tail-2-shipped-v0-19-7-tier-3-prose-docs-re-v.md @@ -0,0 +1 @@ +`[2026-07-06]` **Tail-2 SHIPPED (`v0.19.7`) — Tier-3 prose docs re-vendored + persona_state body-shape aligned.** worldtree-dev landed the Tier-3 persona/memory/persona_state PROSE docs (`c9e59ec`, on origin) — they serialize as freeform `Any` in the OpenAPI JSON, so the **prose is their source of truth** (my earlier "2.3.0 = #347-only, tail-2 collapsed" was half-wrong: the JSON was #347-only but the prose is separate). Re-vendored `docs/conversation-api-spec.md` (markdown pin, tolerate_drift; `worldtree-spec-rev` 879cefe->c9e59ec, SPEC-PIN history row added). **Consumer fix:** `--set-persona-pad`/`_set_persona_probe` was sending `{pad:[list]}` but the canonical SET body (#317) is `{pad:{pleasure,arousal,dominance}}` (named dict) — aligned it + added a len!=3 guard; updated contract #2 note + set_persona_state docstring + tests. The `set_persona_state` WRAPPER was already correct (freeform pass-through); only the CLI probe drifted. TDD (probe test asserts the dict; +1 wrong-count test). Suite **602 green**, ruff clean. **heid-code-review on #347 (dispatched + returned this session): UNANIMOUS ZERO DRIFT** (Gróa/Hulda/Regin all confirmed the hide-existence 404->`AuthoredHistoryUnavailable` routing holds at wrapper/probe/test layers + the extra="forbid" body-omission + the deliberate write-vs-read 404 asymmetry — confirmation-not-discovery for a well-TDD'd slice against a prescriptive contract). worldtree-dev foot-guns banked in SPEC-PIN + [[reference_worldtree_affect_surface_map]]: ocean single-letter `{O,C,E,A,N}` on /agents/define (#348) vs spelled-out on /characters; memory `{embedder_version, tier3_dreaming}`, stm_* deprecated, allows_world_scope removed->422; only `valence` still 422s. diff --git a/persistent-memory.d/2026-07-06-the-bash-tool-s-grep-is-a-ugrep-wrapper-ignor.md b/persistent-memory.d/2026-07-06-the-bash-tool-s-grep-is-a-ugrep-wrapper-ignor.md new file mode 100644 index 0000000..cbf4381 --- /dev/null +++ b/persistent-memory.d/2026-07-06-the-bash-tool-s-grep-is-a-ugrep-wrapper-ignor.md @@ -0,0 +1 @@ +`[2026-07-06]` **The Bash tool's `grep` is a ugrep-wrapper (`--ignore-files -I`) that silently returns NOTHING on some files** (e.g. `src/ratatoskr/web/static/index.html`) — greps for `