CLAUDE.md · diff

git:20260918.c7018ed to git:20260924.ffbcd1a

22 added, 37 removed. Audit A to A.

# Engram — context for Claude Code
**What this is:** a graph-based, durable, inspectable long-term project memory for AI coding assistants (Claude Code first). Local-first, user-owned, graph-first UI. The **reasoning/decision memory** layer (why/decided/what-bit-us) — not a code-structure graph; the wedge is the editable IDE-embedded graph pane + conflict surfacing + local. The line since 0.8.0: *the most powerful and feature-rich inspectable graph long-term memory for software development with AI agents, based on reproducible research.*
- **THE GRAPH IS THE MEMORY OF RECORD — this file is only a keyword index.** The session brief is auto-injected; `search` engram before any non-trivial work and follow the write-verdict protocol. Details, rationale, gotchas, and the full history live in this repo's graph (`.engram/graph.tepin`, daemon on 8787) and the eval workbench graph (`eval/.engram`, project `eval`, scientific ontology Claim/Method/Question/Finding/Source/Task). PLAN.md was retired 2026-08-04 (merged here); `PLAN §…` references in code comments point at git history.
+ **THE GRAPH IS THE MEMORY OF RECORD — this file is only rules and a keyword index.** The session brief is auto-injected and opens with the **Current cycle** (open work stamped with the working version); `search` engram before any non-trivial work and follow the write-verdict protocol. Details, rationale, gotchas, and the full history live in this repo's graph (`.engram/graph.tepin`, daemon on 8787) and the eval workbench graph (`eval/.engram`, project `eval`, scientific ontology Claim/Method/Question/Finding/Source/Task). PLAN.md was retired 2026-08-04 (merged here); `PLAN §…` references in code comments point at git history.
## Hard rules (locked — don't relitigate without reason)
- Open-source, MIT; optimize for docs & DX. Product name **"Engram Alpha"**, binary `engram-alpha` (repo/plugin namespaces stay `engram`; JetBrains package `dev.techtheist.engram` — don't rename).
- **Rust** backend (rmcp, rusqlite bundled, sqlite-vec, fastembed, tepindb) — no Node runtime dep. **Vue 3.5 + TS + Vite + Bun**, Pinia, Tailwind 4, Vue Flow; `bun run lint` / `lint:style` in `frontend/`.
- Embeddings/models **local-only**; **no LLM in the daemon, ever** (encoder-only mechanisms); models nominate, people judge.
- **Retrieval changes cite a measured `eval/` run or they don't ship** (since 0.8.0).
- **9 node types (8 + Tombstone since 0.9.0) / 7 sentence-shaped verbs** on the default ontology; no new types, no `relates_to`; durability governs staleness; high-value edges are `replaces`/`conflicts-with`. Per-graph ontology/policy config exists since 0.7.0, but THIS repo's graph stays on the default ontology permanently.
- **Hard delete is user-only** (pane); MCP deliberately has no delete/register/pin tools. Writes are silent; transparency is the pane. One workspace version for every crate, stamped from the tag; `claude-plugin/.claude-plugin/plugin.json` must match (test-enforced).
- Multi-user & repo sync: **out of scope permanently** (future enterprise product). Dogfood on the **aggressive** skill variant (relaxed is the user default). Eval ladder max **1500 notes**.
## Where things go
`crates/engram-core` (engine, Store trait + sqlite/tepin drivers, policy, config, cortex) · `crates/engram-mcp` (rmcp tools) · `crates/engram-http` (axum API + embedded pane) · `crates/engram-cli` (`engram-alpha`: serve/mcp/doctor/setup/migrate/stop) · `frontend/` · `eval/` (engram-eval bench) · `eval/knowledgedrift/` (a pointer README only since 2026-09-16 — **KnowledgeDrift** lives in its own repo **github.com/techtheist/knowledgedrift**, main = v2: generator vendored, worlds frozen, engram-core a rev-pinned git dep behind `--features arms`; a local `.cargo/config.toml` `[patch]` points it at this checkout while a cycle is open; the gate/knob probes are uncommitted `examples/` there; that repo never mentions how the bench changed engram; old receipts `eval/results/*-knowledgedrift-*`) · `engram-jetbrains/`, `engram-vscode/` · `skills/engram/{aggressive,normal,relaxed}` + `claude-plugin/` (verbatim copies, sync-tested).
## Workflows & sharp edges
- **Pane/daemon rebuild: `scripts/deploy-pane.sh` only** (never hand-chain build/install/restart); after any redeploy, `/mcp` reconnect — live stdio sessions keep the OLD binary and stale tool descriptions.
- - **Release:** CHANGELOG section (one `## v<version>` per release) → push → `gh workflow run draft-release.yml -f version=X.Y.Z` → publish the draft. Bump the graph's working version (`set_version`) when a cycle OPENS, not at release.
- - **Eval:** `cargo run -p engram-eval --features fastembed -- --series|--ladder|--sizes N|--tricks|--posttune|--floor|--bench|--chains|--window|--longmemeval s` — receipts in `eval/results/`; `--distractors 0` = question-everything mode; `--longmemeval` downloads SHA-pinned into `eval/data/` (gitignored).
+ - **Cycle open:** `set_version` in the graph + bump `Cargo.toml` workspace version and `claude-plugin/.claude-plugin/plugin.json` together; record the cycle's plan as an open Intent (it then leads the brief).
+ - **Release:** CHANGELOG section (one `## v<version>` per release) → push → `gh workflow run draft-release.yml -f version=X.Y.Z` → publish the draft. Bump the graph's working version (`set_version`) when a cycle OPENS, not at release. Sharp edges: `cargo fmt` before the release commit; CI's clippy is newer (`cargo +<CI-version> clippy`); delete stale drafts by release id, never by tag (Caution `00d6s063tpjx`); a `startup_failure` dispatch is re-dispatched, a starved-runner flake gets `gh run rerun --failed` (Caution `00bywotv5tx7`); never `cp -f` over an executed binary on macOS (Caution `00byqnk4w09h`).
+ - **E2e suites:** `crates/engram-cli/tests/{e2e,e2e_wiring,e2e_encryption}.rs` (harness `e2e_common/`), ride `cargo test --workspace`. Screenshots: `scripts/screenshots.sh` (local only, never CI); a surface missing from `frontend/demo/data/` is missing from the docs too.
+ - **Eval:** `cargo run -p engram-eval --features fastembed -- --series|--ladder|--sizes N|--tricks|--posttune|--floor|--bench|--chains|--window|--shapes|--longmemeval s` — receipts in `eval/results/`; `--distractors 0` = question-everything mode; `--longmemeval` downloads SHA-pinned into `eval/data/` (gitignored).
- Search-before-write; every write response is a verdict (matched → merge, suspects → judge now, warnings → check canon).
- ## Chronicle (slim — search the graph with these keywords for the full story)
- - **v0.9.8** (2026-09-18, OPEN): *unbound sessions refuse writes* — issue #11 (tjuerge, Windsurf JetBrains): a resumed conversation or an IDE restart spawns a NEW bridge → a new core session back on the fallback rung, and captures went to the home graph for hours with no signal. Four moves: (1) **the bridge relays its ladder rung** upstream (`clientInfo.description` = `bound_by=<rung>`, `name` = the end client's name; `ResolvedTarget.bound_by`, `engram_mcp::BoundBy`, `Engram::record_client` in the `initialize` override; census rows carry `client` + `bound_by`); (2) **`bound_by=home` refuses writes** addressed to "this project" (`write_engine_for` on every write tool; teaching error names client, reason, the `brief(project:)` call, the roster; explicit `project` passes; default-agent-project rung stays writable; `brief(project)` stamps `Brief`); (3) **write receipts** — every write verdict carries `project`, the default-project rung adds `binding_note` on its first write only (`stamp_write`/`reply_write`); the brief's first line names the graph (`# Engram brief — project 'x' (/root)` / `— the home graph (user-level, no project)`, hub `brief_for`); (4) **`/` and `$HOME` never host a project** — the Windsurf JetBrains plugin launches from `~` on this machine (writable → a stray project "techtheist" with a second graph at `~/.engram/graph.tepin`, four times); `root_cannot_host` in the resolver falls through to default/home, `registry::register` refuses both. Rule/instructions/skills teach "refused write = rebind, retry; read `project` on every verdict"; Windsurf rule gains the VERIFY paragraph. Windsurf hooks (JetBrains `~/.codeium/hooks.json`, `pre_mcp_tool_use` blocks via exit 2, cannot inject context, no workspace field, hook cwd = workspace) were assessed and NOT used: a hook can't name its own MCP session. Lead for later: `post_cascade_response_with_transcript` hands a JSONL transcript path — possibly the plaintext channel the encrypted-Cascade-history insight waits for. **Same day, `GET /guide`** — the operator's manual (`crates/engram-http/src/guide.md`, `OPERATOR_GUIDE`, text/markdown, project-independent): every Settings surface as HTTP recipes + ground rules (config is the user's decision, read-before-write whole-document PUT, nothing in use dropped, say what changed, reinstall skill + `brief.ontology.show` after reshaping) + the pre-digest settings review; MCP INSTRUCTIONS, skills ×3 + plugin copy (new section "Changing how memory behaves"), agents/*.md, digest skill step 1b, COLD_START_BRIEF and docs/customization.md point there; test `guide_is_markdown_and_names_only_real_routes` proves every `METHOD /path` the guide names is a route. Doctrine shift: "config is a user gesture" now means the assistant may execute it over HTTP on the user's explicit ask — still no MCP config tools.
- - **v0.9.7** (2026-09-17, RELEASED 2026-09-18): *the icon arrives* — the user-drawn icon (`frontend/public/engram-{light,dark}-{64,512}.png`, `engram-1024.png`, `engram-svg-no-box.svg`): `EngramMark` is now the boxless mark with variable colors (bars `currentColor`, face `--mark-face`); the top bar shows `engram-light-64.png` on `engram-purple` and the mark in a sunken accent-colored chip on IDE skins; System info opens on a ≤256px icon (dark box on `*-light` themes, purple box elsewhere); `favicon.svg` = the boxless mark with a `prefers-color-scheme` face; README shows the 1024 render at 300px under the badges; page title "Engram Alpha - AI Memory". Final chip rule after three rounds of local testing: one rule for every IDE skin — box `--interactive-primary` (the row's button color), bars `#0a0a14` at `--mark-bars-opacity` 0.8, face `#fff`; a light/dark split was tried and dropped. **Plugins:** JetBrains tool-window icon ×4 (16/20px, `#6C707E`/`#CED0D6`, viewBox `-4 -4 128 128` for ~1.75px padding) + VS Code `media/icon.svg` (`#C5C5C5`) are the monochrome E+A mark the user drew; marketplace icons (`META-INF/pluginIcon.svg` = 40×40 SVG wrapping a 240px base64 PNG, `engram-vscode/media/logo.png` 256px) rendered from `engram-1024.png` with `sips`; both plugins say **Engram Alpha** everywhere (plugin.xml name, tool window `id="Engram Alpha"` — a new id, layouts reset once — editor tab/virtual file, VS Code container/config titles, editor panel, status item); local build stamps bumped to 1.0.0 (`gradle.properties` `pluginVersion`, `engram-vscode/package.json`; CI still stamps from the tag). Gear menu: `max-height` cap on `100dvh` (iOS Chrome's `100vh` includes the toolbar — the tail was unreachable). Screenshots regenerated (`scripts/screenshots.sh`; demo System fixture says 0.9.7), the three hand-made full-pane shots retaken by the user from a real graph.
- - **v0.9.6** (2026-09-16, RELEASED 2026-09-17 at 2c760e9): *the bench spoke lowercase, and the queue learned to listen* — KnowledgeDrift **v2** (merged to the bench repo's main 2026-09-16: shared-vocabulary lowercase subjects, a crossed phrasing, natural-null controls, reworded/clause/synonym shapes, the path read, an additive score = families 800 + signal 100 + tokens 100) had measured engram 0.9.5 at **741 @500 / 718 @1500** with three weaknesses (Problem `00d9cqhozpjx`). One session, four levers, each measured before it shipped: (1) **subject guard v3** (Decision `00db826g6qjx`) — the 0.9.4 guard read only capitalised tokens, so on lowercase subjects the title-NLI path never fired (t1 0.04, drift 47%); now names are read from the first clause and, failing that, the subject is the longest run of ≥2 content words both first clauses share, refused when a differing content word qualifies it on either side (bayou/dale), first four words = the subject the overlap strips; `engram_core::title_pair_admissible/title_pair_admission` public so the probe measures the shipped rule; (2) **clause read on the unnamed path only** (Decision `00db827h6qjx`) — titles judged whole and cut at em dash/semicolon, stronger contradiction wins; on the named path the same read pushed 5 eval-graph + 2 dogfood same-subject-different-fact pairs over the gate, so it is path-gated (`nli_title_hint_for`); (3) **tombstone title channel** (Resolution `00db828i6qjx`) — a rewrite whose folded title equals a live marker's victim title warns `tombstoned` whatever the vectors say (resurrection_warned 0.81→1.00 @100; a 24-deep vector scan was rejected: it warned 38% of purged rewrites about other markers); then the 500 rung showed six rewrites absorbed as *duplicates of unrelated same-type notes* at 0.90 (boilerplate bodies) → (4) **the duplicate match refuses titles that demonstrably name different things** (Decision `00db8u8h7qjx`, `subjects_differ`; undecidable titles still match). Two levers measured and left alone: the **weak line** (Insight `00db829j6qjx`: oblique answers and natural nulls score the same on the top hit, q50 0.54 vs 0.64 — the 40% hedge is structural, every lower line costs ten times what it buys; `ENGRAM_WEAK_LINE_DEBUG=1` prints both probe families) and the **crossed phrasing** (Insight `00db85877qjx`: a cross-encoder ceiling — keyword weight 0→0.15 moves it 0.10→0.08 @100, vote/floor/full-note nothing or worse). Real-graph gate: **`engram-eval --sweep-replay PATH`** (Decision `00db82ak6qjx`) replays the sweep on a copy — dogfood 0 new / 3 of 87 dismissed would re-queue (0.9.4: 4), eval graph 0 new. Receipts (knowledgedrift repo `results/v2/reference-arms/`, 0.9.5's under `…/0.9.5/`): **500 three seeds 816 (813–818) at 73% (72–73), was 739 (736–741) at 70%; 1500 801 at 69%, was 718 at 66%** — contradiction 46→70% (68–72) (t1 0.04→0.75–0.85, t2 0.08→0.52–0.58, t3 false alarm 0.00→0.05), drift 44→91% / 48→93%, deletion 93→100%, abstention 100→99% (natural_fp 0.02, the per-run line refit), everything else to the digit, baselines byte-identical; the v1 500 world holds at 86% / 518 (was 85% / 511, deletion 90→100%) Housekeeping: the workspace still listed `eval/knowledgedrift` as a member after the move (cargo refused to build at HEAD) — dropped; `brief(project: knowledgedrift)` REBINDS the session, five notes landed in the bench graph and were buried there with tombstones (`replaces`) and re-added here — pass `project: "engram"` explicitly after any cross-project brief.
- - **v0.9.5** (2026-09-13, RELEASED 2026-09-14 at 7395988): *the bench fixed the product, then became a product* — **2026-09-13: KnowledgeDrift** (`eval/knowledgedrift/`, own crate `knowledgedrift`): one seeded world → JSON script of ten protocol ops (inscribe import/write, link, supersede, release, purge, settle, recall±window, suspects, lineage) → any adapter → transcript → grader; eight task families (retrieval with 10% stale-sibling pollution, abstention, currency+lineage, contradiction ladder in three tiers with negatives, drift, deletion honesty + resurrection, rationale via edges, temporal), every probe pass/fail; **success** = passed / ALL tasks (N/A = failed), composite = macro mean (N/A = 0), **score = 100 × composite × clamp(10·S, 0.1, 10)**; six in-process arms, `--export`/`--grade` for Mem0/LangGraph adapters (next). First run (`2026-09-13-knowledgedrift-100-500-nogate.*`) showed the suspect queue raised 0/16 planted contradictions → **gate probe** (`examples/gate_probe.rs`) → **title-NLI nomination path** (`policy.conflict_nli_gate` 0.80, strict subject guard + ≥1 shared content word past the subject phrase, `null`/pane 0 = off; engram Decision `00d5ekolq3k8`, Caution `00d5xf6rqpjx`): @500 contradiction 58→75% (t1 0.06→0.94), drift 53→91%, success 83→85%, score 472→511 (`2026-09-13-knowledgedrift-100-500.*` vs `…-nogate.*`). The first version (0.70, lenient guard) raised **56 false alarms on the dogfood graph in one sweep** (release notes, same-subject unrelated facts); the probe re-measured against those rows + a new `collider` negative shape produced the final rule (4/56). Lessons: similarity cannot separate contradiction from restatement (MemStrata reproduced inside the gate), titles judge better than title+first sentence, co-reference AND same-subject-different-fact need guards, a generated bench must be replayed against the dogfood queue before a nomination rule ships, a dump must pay for its noise (multiplier floor 0.1), success must count what a system cannot attempt. **2026-09-14:** three seeds at 500 (engram 85% (84–85) score 525 (511–543), langmem = rag 63% (61–66) on every seed, mem0 59% (57–61), grep 53% (51–55); success stable to ~1 point, tier-3 false alarm the widest column), `--pollution-shape stale|twin|late` (twin → no ranker separates the siblings, engram `stale_above` 0.21→0.64 while the drift queue notices 98%; late → flat stores byte-identical, engram 0.21→0.35: recency is a weak prior), Mem0 (`infer=False`) and LangMem (store + semantic index) adapters, and **KnowledgeDrift v1 as its own repository** (github.com/techtheist/knowledgedrift: generator vendored, seven worlds frozen with a golden-digest test, grader dependency-free, engram-core a rev-pinned git dep behind `--features arms`, submissions by PR; that repo never mentions how the bench changed engram). **Release incident 2026-09-14:** v0.9.4 had been published 2026-09-12 while this file still said OPEN; a `gh release delete v0.9.4` meant for a stale duplicate draft deleted the PUBLISHED release (gh resolves a tag to the published release even when a draft shares it — delete drafts by id via the API); the tag survived at dfa16a2 and the original draft-release run was rerun to rebuild the nine assets for re-publishing.
- - **v0.9.4** (2026-09-12, RELEASED at dfa16a2): *two external benches* — a literature sweep (~120 papers as 7 grouped Sources in the **eval** graph, 6 Claims, 8 Questions, 6 Tasks; the register "rationale memory for coding agents, LLM-free, human-judged" is empty in the literature) picked two runs. **ForgetEval** (arXiv:2606.15903, `eval/forgeteval/`, REST-only adapter, receipts `2026-09-12-forgeteval-*`) is reported **per family, never summed** — its "decay"/"amnesia" are explicit releases, not time decay, and engram maps release to the user's tombstoned delete whose marker stays findable by design; two readers: role-blind (decay/amnesia 0%) vs role-aware (supersession 100 / drift 99 / purge 100 / decay 100 / amnesia 92%, adversarial 240/385 vs the reference's 244 — same three hard categories). What it found: (1) over REST a hit's only role signal was the type NAME → **every search hit now carries `tombstone: true`** when it plays the role, stamped from the ontology (Decision `00d36lue869d`); (2) the adapter zeroed `knee_cliff` to disable it, but **0 is the harshest knee trim** (every relative drop clears it) — amnesia sat at 55% on a config typo; `null` is off, **config now refuses 0** with a teaching error (Caution `00d36wxyia9d`); (3) the fixed 0.22 floor blinds a 6-note short-fact graph (Caution `00d35pgyf19d`, third register under Problem `00b227i6tdob`); first run kept as `*-run1-kneebug.*`. **The rake test** (`eval/rake/`, Method `00d2fbtk8k8d`): persist–clear–act on an invented Python fixture, three arms (none / curated CLAUDE.md / engram) × three tasks, headless Sonnet under fixed budgets, executable oracles on the diff. Phase 1 (9 runs, $2): baits too weak, the fixture's code guided every arm. Phase 2 (27 runs, 3 seeds, $8.41, `2026-09-12-rake-phase2.json`): memory-only baits separate the arms — T1 retry budget + sync-outside-transaction: none 0/3, curated 3/3, engram 2/3 + 1 unscorable (method-shaped push_batch the oracle couldn't bind); T3 stale config docs: none 2/3, curated 3/3, engram 2/3 + 1 that **stopped to ask** the absent user about the deprecation cleanup (a third outcome phase 3 must score); T2 checksum-skip bait never bit anyone. Curated ≈ engram on a 10-note world at equal cost ($0.34/run), as expected — the crossover argument lives at scale. Receipts now carry a `YYYY-MM-DD-` run-date prefix (`scripts/date-results.sh`). **Same day, second half:** 0.9.4 re-baseline reproduces 0.9.0 to the digit (Insight `00d3geak5lay`, built from a clean HEAD worktree); **the ladder learns history** — `--history` puts every note in a 5–10-note single-component session with a turn index, distance = `2·|a−b|+1` (both endpoints counted, user's convention), columns `reach@5`/`reach`/`hist-only`/`hist-dist` for every arm; measured: the walk is +0.07 at depth five for rag AND engram (0.79 → 0.86 at 1500, a tie at 297 vs 2721 tokens), diversity demotion live on a multi-session corpus is recall-free, all-delivered reach favours rag only through breadth (eval Finding `00d3kyeehuay`); **`--collision R`** mints same-subject untested colliders — 50% costs rag and engram ~3 points R@5 and 6–8 oblique alike, grep untouched, a crowding measure not a lever; both knobs byte-identical when off (golden FNV hash test). **ForgetEval abstention layer** (`engram-mcp` reads the verdict over the MCP HTTP transport, `grep` baseline, 3 never-inscribed controls per case, fp/hedge/separation-AUC beside the family scores): engram answers 0/3000 controls where Lethe answers all, but hedges on 99.5% of real template queries — on six-note graphs the phantom-fitted weak line has nothing to fit and the 0.85 default rules; separation 0.80/0.90 says the scores could carry a per-graph line (Insight `00d3kvkchuay`, Finding `00d3kuz9huay`) — Problem `00b227i6tdob`'s fourth register. Found on the way: an MCP session captures its engine ONCE at creation and keeps reading an orphaned store after a wipe (Problem `00d3jtpkjlay`, open; adapter re-handshakes per case). **Pane: code refs editable** as one-per-line text in the drawer + create panel, Checkup lists drifted notes (Resolution `00d3jao76lay`). READMEs restructured with `<details>` spoilers (main ~45%, eval ~56% folded); ForgetEval README drops timing (contended runs).
- - **v0.9.3** (2026-09-09, RELEASED at 93bd8a7): *the pane fits any width* — a six-width test rig (157/214/318/542/613/794 px, same-origin iframes over the demo dev server, `node_modules/.thin/`, not committed) found the burger AND gear falling off the bar under 250px: **the top bar wraps** (icons row one, view switch row two; SidePanel/Feed/History start 9.4–10rem down), segments tighten ≤300, minimap hides ≤260, health strip wraps ≤860 (Decision `00cyagaz3k8d`); **swipe-to-close** on drawer headers, touch only (Decision `00cyagay3k8d`); **demo badge per screen, CSS only** — `:has()` on the app root + CSS anchor positioning above `.action-bar` on narrow feeds, double fallback to the corner (Decision `00cyag9x3k8d`); **Graph settings crash** — demo config/presets lacked `session_diversity_demote` (0.8.10), StepperInput now tolerates an undefined modelValue (pane-newer-than-core is a real VS Code pairing), demo `restore()` backfills old sessionStorage dumps (Caution `00cyaga04k8d`); `loading` starts true (no "No memory yet" flash), leaving graph for feed OR history closes the detail drawer; **CSS audit** — undefined `--border`/`--bg-primary` fixed, literals → tokens, dead rules gone, breakpoint + z-index table at the top of app.css; the grouping plan (glass pill ×6, popover shell ×6, eyebrow ×10, edit-input trio ×2, must land in `@layer components`) is recorded, not applied (Insight `00cyagb24k8d`). README rewritten lighter (Decision `00cyagc34k8d`).
- - **v0.9.2** (2026-09-04, RELEASED at 0d81c40): *tombstones guard the write path* — the 0.9.0 Tombstone was findable but guarded nothing (active → never `superseded`; sits out the scan → never `in-active-conflict`; duplicate match is same-type; Problem `00cox6i3pj8d`). Now: **`tombstoned` write warning** (role-based, cross-type, carries the tombstone's `note` = why; never blocks); **delete mint carries the buried content** (victim body as `**Removed text:**`, tags, code_refs; pane "Keep the removed text" tick, `keep_text=false` = purge shape) and **rehomes the victim's `about` edges** onto the tombstone (same edge id); **search `tombstone_note`** when a hit carries the role; **`check_claim` `retracted` bucket** (role-sorted before NLI, score in `entailment`; pane group; write-time canon check skips tombstones — one channel per fact); **write-time suspects skip tombstones on both sides** (found by the new MCP test: a bury write paired the tombstone with its victim, inviting a `replaces` that would archive the marker); **the assistant's bury gesture** = add_note Tombstone `Removed: …` + link `replaces` victim (no new tool; 26 stays), taught in instructions + all three skills. Semantics locked: superseded = a successor exists, follow it; tombstoned = killed without one, re-adding is the error. Docs fixed where they implied the mint links its victim.
- - **v0.9.1** (2026-09-02): *the pane stops looking foreign, and the docs shoot themselves* — **SelectMenu** replaces all ten native `<select>`s (styled trigger + body-teleported listbox, keyboard nav, flips upward; the native popup looked like another application on Windows, Decision `00cl7d85lj8d`); ontology type card wraps its Durability/Rank-prior row and moves brief **cap/excerpt** onto a row of their own. **Bob lifecycle hooks** (IDE 2.0.2 / BobShell 2.0.1): `setup --cli bob` installs the portable brief script under `.bob/hooks/` and registers it in `.bob/settings.json` — plain-stdout SessionStart, no envelope (unlike Devin), `sh`-prefixed, workspace-relative, 30s timeout; foreign settings get the snippet printed (Decision `00chelyixmxw`). **Screenshot pipeline** (`scripts/screenshots.sh` + `frontend/scripts/shots/`): headless Chromium drives the demo build, manifest per PNG, fresh context per shot, frozen clock + deterministic layouts + motion off = reproducible; 16 shots (9 regenerated, 7 new: node detail, ontology card, custom fields, memory lens, system, history screen, claim check), the standalone/VS Code/JetBrains three stay hand-made; local-only, NEVER CI (mac vs Linux font rasterization). Gotcha: Chromium's scroll-into-view never settles inside the gear menu's capped scrolling body — menu rows are clicked by dispatch (Caution `00cl9kyxmj8d`, Decisions `00cl9kyvmj8d`/`00cl9kywmj8d`). Demo seed caught up with 0.9.0 (custom fields `impact`/`tracker` with values, a Tombstone note, system fixture 0.8.1→0.9.0 — Insight `00cl9kzymj8d`: a feature missing from the demo seed is a feature missing from the docs). Also: `timespec` calendar shifts are checked arithmetic (an absurd month/year count reads as "not a time", never a wrapped instant); the seal key file is created 0600 rather than chmod'd after; **docs sweep** — 13 fixes against code and CLI help (graph.db-as-default, home.db→home.tepin, installer-wires-repos, 8→9 types, agent rosters, SECURITY's shipped CORS allowlist, plugin README binary name; Insight `00cl7d96lj8d`), plus a docs/pane.md section for the session-history screen, which had none.
- - **v0.9.0** (2026-08-30): *deletion leaves a trace, fields are yours, rest is sealed* — **Tombstone type role** (9-type default ontology, Retraction in research, new `general` preset; tombstone-role types sit out the conflict scan and never decay; hard delete offers "leave a Tombstone" with reason — and the mint is EXEMPT from required-field enforcement, deletion isn't authoring, Decision `00cfetz4muxp`); **custom fields** (FieldDef in GraphConfig: text/number/bool/date/enum/url, required/applies_to/indexed/show_in_brief; engine-boundary validation with teaching errors naming the roster; reserved-name shadow ban; MERGE patch, null deletes; rename-field = migration; pane sub-menu with built-in-fields reference; indexed values join both search channels); **bitemporal `date_field`** (after/before re-aimed at date-kind fields, from..to = interval overlap, unaimed clock errors); **at-rest encryption** (two switches: graph OFF / history ON default; state in each store's OWN meta `plaintext|sealing|sealed|unsealing`, crash-resumable; `crate::seal` generalizes 0.8.4's HistoryKey verbatim; **`_kw` blind keyword index** — identity tokens plaintext / keyed HMAC sealed, BM25 bit-identical by golden test; history gains its first keyword channel; `POST/GET /encryption` progress; exports stay plaintext; sqlite refuses). **Receipts:** ladder reproduces 0.8.10 to the digit (`eval/results/2026-08-30-0.9.0-ladder-run.log`); posttune FP 0.00@100 / 0.02@1500 — the one honest delta: single-stream BM25 shuffles deep candidates, the weak line re-fits 0.898→0.878 at 1500 (FP 4→7 of 375 controls), top ranks untouched everywhere; canonical protocol `--ladder --posttune --sizes 100,1500` (bare `--posttune` exhausts the 4096-name space at 1500; raw-ladder FP 1.00 is NOT a regression — README's engram row splices the posttune cell, now †-footnoted; Insight `00cfety3muxp`). Also: **Nebula layout removed** (three remain; Tombstone `00cf7rx7iuxp`); **installers stop wiring unasked** (--cli is the opt-in; serve's nudge names the unwired agents with the exact command, Decision `00cffaw0nuxp`); **Windows path escaping** in every config writer/snippet (codex refused its whole config.toml over `\U` — json_str/toml_str, Resolution `00cfetx0muxp`, Caution `00cfety1muxp`); **seam-test sweep** (~20 tests: sealed store × verdicts/suspects/brief/merge/timeline/redaction, keyless placeholder reads, pre-0.9 export+config shapes, handshake unsuccessful branches as pure-fn matrix + 2 e2e journeys; core 232, e2e 8; Resolution `00cfeu05muxp`).
- - **v0.8.13** (2026-08-29): *locks release and schemas teach* — **identity-checked engine cache** (issue #8 lock report: `Hub.open` cache hits re-stat the backing file's dev+ino (`StoreIdentity`); a deleted/replaced store is evicted and reopened fresh — tepin-born — instead of served from the orphaned inode; Problem `00cddnieb6xq`); **honest stop** (PID-verified exit — locks release at process exit and /health-silence proved nothing; `/shutdown` → SIGTERM → SIGKILL escalation + port-free check; core exit reordered: bounded 10s engine drain BEFORE `http.abort()`); **version handshake** (`retire_older_core` at serve, bridge bind/rebind, and core start, plus a `bind_or_converge` takeover: an older core is stopped and replaced by the newer binary, a newer one is converged on — never downgrade; a taken port gets 3 health probes before the walk, so a busy core no longer births a split-brain second core); **write tools teach their shapes** (issue #9, Haiku via Devin: `#[schemars(inline)]` on AddNoteArgs/UpdateArgs — batch items were a bare `$ref` hiding every field; vocabulary doc-comments on the two `type` fields; `deny_unknown_fields` on write args — an inline `links` array used to be silently dropped; server `instructions` cut 4.1KB → the contract WITH the 8-type roster and exact call shapes, closing the instructions half of `00c0b7rdbcs4`); **skills show real JSON** (positional pseudo-syntax `link(a, b, answers)` → keyword JSON + an `add_notes`-then-link worked example in all three variants; digest's "batch into add_notes… link as you go" contradiction resolved, near-empty-tree early stop, files-not-directories line; cold-start brief appends `describe_ontology`'s output; AGENTS.md roster gained Anchor + call shapes; aggressive's self-edit footer scoped to the engram repo). Count truth: **26 MCP tools** (0.8.11's "24" was a miscount).
- - **v0.8.11** (2026-08-26, RELEASED at f713aa0): *one tool binds and briefs* — **`brief` ABSORBS `set_project`** (24 tools; Decision `00c7ntibghzp`): passing `project` (name/id/absolute path/"home") rebinds the session atomically and returns that project's brief as markdown behind a "Session rebound" line — the issue #4 field report showed the injected brief-first guidance overruling the reporter's set_project-first rule, so the two gestures became one and there is no wrong first call left; resolve-first (a refusal leaves the binding untouched), fallback hint + INSTRUCTIONS + skills + docs all teach the single gesture; SEMANTIC CHANGE accepted: brief(project) no longer read-scopes without rebinding (cross-project peeks = search/list_nodes project args, GET /brief?project=). **Windsurf project wiring** (#7, Decision `00c7nu3fghzp`): `.windsurf/rules/engram.md` always_on rule (critical first line = the brief-rebind; Windsurf has no hooks) + `.windsurf/skills` via the shared install_skills helper. **Devin CLI adapter** (#8, Decision `00c7nucgghzp`): `.devin/mcp_config.local.json` (highest-precedence tier, explicit --db, git-ignored) + `.devin/skills` + SessionStart hook in `.devin/hooks.v1.json` — Devin injects context ONLY via the hookSpecificOutput JSON envelope (plain stdout dropped), so the hook wraps the portable script (awk escaper, test-locked). Release friction: first draft-release dispatch died `startup_failure` before any job (GitHub-transient, workflow unchanged) — the fix is re-dispatch, `gh run rerun` doesn't apply.
- - **v0.8.10** (2026-08-23, RELEASED at 732e5b2): *search mixes sessions* — **session-diverse delivery default-on** at `policy.session_diversity_demote` 2 (rank-based at the final cut only, top of a three-seed free zone, inert on the LongMemEval chat register; hits carry `session_id`; Resolution `00c0smup8jlv`); **MCP replies tidied at the ok_json funnel** (ISO instants, null/empty pruned — MCP only, pane/exports raw; Decision `00c0qfxt7jlv`); **delivery-floor bake-off: NEITHER attack ships** (full-note rerank input wins the note register but collapses chat R@5 0.96→0.78; dial-three q25 recall-free ≤500 notes but not 1500 — Problem `00b227i6tdob` stays open pending a chat-register fit; Insight `00c0xcaj9jlv`); eval: `--sessions` bench, `--lme-turns` short-LongMemEval loop, floor rows, README restructured to read historically (baselines re-measured on 0.8.10, replicating 0.8.2 to the digit).
- - **v0.8.9** (2026-08-22, RELEASED at afe28a6): *the agent binds itself* — **`set_project`** (25th MCP tool, Decision `00c0b7i9bcs4`): a session rebinds ITSELF to a registered project (name/id/any absolute path inside the root) when its client advertised the roots capability but answered `roots/list` empty (issue #4 field gap: Windsurf, Devin CLI); refusals list the roster, the reply embeds the target's brief, mutable session `Binding` behind one RwLock, hub-level **session census** (touched per tool call, 30-min TTL) under `/system processes.sessions` + pane System panel; brief opens with a set_project hint when a session lands on the home/default-agent rung; skills + docs/runtime.md teach it, one AGENTS.md line automates it. **Every tool description cut to its contract** (Decision `00c0b7rdbcs4`: descriptions are per-session context on EVERY client — verdict duties and safety lines stay, detail moves to arg docs; server `instructions` + response-note strings still uncut). **Registry resolution fix** (Caution `00c0a0697tx7`): `ProjectEntry.db` is wiring, not truth — every reader goes through `resolved_db()` (`.tepin` sibling wins), so cross-project surfaces stop skipping live tepin stores as "db missing". **NLI scoreboard** in Checkup (`GET /conflicts/agreement`): hint-vs-verdict agreement over judged suspects — dogfood graph says 67.5% over 40 hinted pairs, false alarms dominate the errors; read-only, never a calibration input (dial one reads similarity, not the hint). Scope re-cut same day (Decision `00c0lx7phxl0`): session-diverse ranking + delivery-floor work moved to next cycle (bench BOTH floor attacks: dial-three quantile AND wider rerank input), **grep_history ABANDONED** (vector over history suffices; literal grep lives outside engram). Release friction: draft-release runs all four component suites at once and is systematically more starved than a push run — `wait_core_healthy`'s 30s blown once ("core never became healthy", same-commit push run green), rerun cleared it (Caution `00bywotv5tx7`, second symptom).
- - **v0.8.8** (2026-08-21, RELEASED): *one heavy core, everything else light* — the machine core (`engram-alpha core`, hidden, spawned detached) owns every store lock, the three models, the pane, and all MCP sessions; `serve` is a converge-or-spawn launcher that registers the repo and EXITS; `mcp` is ALWAYS a light stdio bridge (the direct-open fallback that could turn a session into a second 600 MB store-holder is removed on every backend). Client leases (15s heartbeat, 45s TTL, client name from `initialize`) feed `status`, `/system`, and the pane's Processes census; `stop` is an orchestrated loopback `POST /shutdown` (PID-kill fallback); after 15 idle minutes the core drops all three ONNX sessions (~845→150 MB, lazy reload 0.1–0.5s, `ENGRAM_IDLE_UNLOAD_SECS`, health/status/lease pings exempt from the clock). `--db` is optional: the binding ladder is explicit `--db` → client MCP roots → usable cwd → **default agent project** (pane setting, `~/.engram/settings.json`) → home, rebinding on `roots/list_changed` — which unlocked **Windsurf** (`setup --cli windsurf` writes BOTH global devin configs; survives its JetBrains plugin's launch-from-`/`, roots-silent client). Folder-as-selector everywhere (any path inside a repo resolves the project; `GET /brief?project=`); issues #3–#6 closed; docs/runtime.md + support matrix. Fixed: brief follows the session's binding (`Hub::brief_for` — home-rooted core had every session briefed on the empty home graph), SessionStart hook asks the scoped brief + probes off-PATH binaries, handshake-first bridge (initialize answered immediately; spawn failure errors the first tool call instead of 180s silence — mcp-go kills at ~60s). Field lessons: never `cp -f` over an executed binary on macOS (per-inode kernel signature cache → every exec SIGKILLed while `codesign -v` passes; deploy now rm-before-cp, Caution `00byqnk4w09h`); CI's clippy is newer than local — verify with `cargo +<CI-version> clippy` pre-push; clap doc comments ARE `--help` (paragraph-split summary/detail convention, Insight `00byry1rl7ea`).
- - **v0.8.7** (2026-08-15, RELEASED at 19966b5): *search learns time* — ONE temporal grammar (`after`/`before` taking day/ISO/relative phrases the daemon resolves, `during_version` read off the recorded version switches, `order:"chronological"|"recent"`) over BOTH `scope:"memory"` and `scope:"history"`, plus `list_sessions` windowing and `GET /search`; `crates/engram-core/src/timespec.rs` owns it (half-open windows, calendar-correct month/year shifts); the window filters before the reranker and both calibrated cuts, and an unreadable date is an ERROR, never a dropped filter. `order:"recent"` folds history restatements under their newest form (`prior` nesting, gated, cannot lose a hit). **The measured surprise: a time window BUYS recall rather than costing it** — mean R@5 0.743 → 0.943 and *oblique* 0.263 → 0.830 on 2100 notes, unanimous across three seeds (`--window` bench, Insight `00bn955lztib`); `policy.window_overfetch` 8 → 2 as a result (depth past 2 is dead weight; the 1→2 step is soft — seed 3 dissents at 180 days). That bench found a shipped-same-day bug: **sqlite-vec REFUSES k > 4096** and `search_vec` quadruples k internally, so any `limit >= 11` beside a window errored and an error empties the search — indistinguishable from the "graph is silent" verdict (Caution `00bn94lkztib`; harnesses must PANIC on retrieval errors, never score them zero). Also: redaction judges entropy **per separator-delimited segment** (model slugs/target triples/URLs survive, structureless secrets still die; named patterns untouched; the 15 already-damaged nodes stay — mechanism, not past), SECURITY.md spells out graph = redacted-not-encrypted vs history = redacted-AND-encrypted; fs-notify pulls the next harvest forward while the 60s sweep stays the guarantee (every watcher failure degrades to the old behaviour); skill teaches multi-query reformulation on a weak/none verdict; hits carry `created_at`.
- - **v0.8.6** (2026-08-13, RELEASED at 72618e5): *the 2026.1 rescue* — issue #1 fixed by **dual JetBrains artifacts** (`X.Y.Z-261` since 261/until 261.* WITHOUT the `intellij.platform.ui.jcef` module dep, `X.Y.Z` since 262 WITH it; `-PplatformLine` picks the line, `processResources` strips the dep with platformLine as a task input, CI builds/verifies/signs/publishes both, `runIde -PsplitMode=false` is what reproduces the classic loader that split mode hid); **update awareness** (doctor always checks GitHub releases, serve notifies at most once per 24h via `~/.engram/update-check.json`, `ENGRAM_UPDATE_CHECK=0` off, never auto-installs); pane bare-minimum chrome breakpoint 400px → 500px. Release note: nine assets, the first release with two signed plugin zips (`publishPlugin` runs twice — the second re-plans because `platformLine` changed).
- - **v0.8.5** (2026-08-13, RELEASED): *the first field reports* — tepin lock safety (`mcp` never direct-opens a tepin store; the direct hub's factory refuses tepin satellites so a bridge can't grab home.tepin; spawn survives a missing `.engram/`; 180s first-run wait; doctor treats core-held stores as owned, not locked — found via Bob IDE holding MedMentor's graph + home.tepin hostage); MCP troubleshooting (#2: bridge reqwest client opts out of proxies — corporate proxy intercepted loopback; `.engram/mcp.log` tees what IDE clients swallow, `ENGRAM_MCP_LOG=0` off; doctor proxy-env warning; docs section); setup/doctor config self-consistency (setup wrote `graph.db` while the store is `graph.tepin` and doctor flagged its own config — setup now writes the resolved path, doctor compares the store a path OPENS). Field lesson: two installed binaries (`~/.local/bin` via installer vs `~/.cargo/bin` via deploy) run different versions silently.
- - **v0.8.4** (2026-08-12, RELEASED at d59c3b5): *the history layer* — sealed session recording (sibling `history.tepin`, zstd→XChaCha20, keystore key, OPT-IN), sweep harvester + seven roster adapters (Bob = one SQLite for IDE+Shell, timestamp cursor), born-in provenance both ways (get_node `born_in`, expand_history `notes`, `list_sessions`), sectioned search behind the calibrated verdict (cascade receipts), pane history view (lanes/zigzag, session-chip links, narrow-adaptive), `setup --cli bob`. Release lessons: cargo fmt BEFORE the release commit; keyring's Linux backend links system libdbus (installed in backend+release workflows, documented for source builds); CI path filters mean .github/docs-only commits trigger no component runs.
- - **v0.8.3** (2026-08-10, RELEASED): *batch width was the memory* — inference batch capped at 2 (`engram_core::onnx`, was fastembed's 256), which cut the daemon's runtime growth to near nothing AND cut eval wall-clock ~40% (BatchLongest padding waste); headline metrics identical on all seven arms at sizes 100+500, only float-summation noise moves. Three suspects measured and REFUTED: ORT arena, per-session thread pools, malloc free-list retention. `scripts/mem-probe.sh` is the harness. Knobs: `ENGRAM_ONNX_BATCH` / `_THREADS` / `_ARENA`. Also *default embedder pinned to fp32* (`onnx/model.onnx`, explicit like the reranker) — the shipped weights now match the ones every `eval/results/` receipt was measured on; int8 stays a ~100 MB option behind a `--ladder` run, and pre-existing int8 provisions are NOT replaced (`provision()` skips a dir that already has a model.onnx).
- - **v0.8.2** (2026-08-09, RELEASED): *merge_nodes* (atomic consolidation, edges rehome, victims archived behind `replaces`); *LongMemEval* — the first corpus we didn't generate (SHA-pinned, as-is ingestion, retrieval-graded, chat ontology as data, ollama/GPU embedder for the harness only); *supersession-chain bench* (`--chains`); corpus vocabulary enrichment (12→25 per slot pool — numbers before/after not comparable); budget sweep (floor/pool levers refuted again).
- - **v0.8.1** (2026-08-04, RELEASED — the pane cycle that opened as 0.8.1 folded in): *knee trim* (TAA-k, `knee_cliff`), *phantom-probe weak line* (auto-tune dial two, graph-vocabulary probes, floor-relative clamp), *"likely not in memory" recommendation verdict* (never cuts), `--posttune` end-to-end mode, pre/post-tune rows in eval README; *tasksource NLI swap* (deberta-v3-small-tasksource-nli default, co-reference false contradictions fixed, own HF ONNX export, MobileBERT stays selectable). Field lesson: *register-dependent score scales* — absolute thresholds don't transfer between graphs, relative mechanisms do.
- - **v0.8.0** (2026-08-03, RELEASED): *measured not promised* — attention metrics (focus/noise/FP), gradation ladder, floor sweep; *calibrated delivery* (`delivery_floor`, strong/weak/none verdict); *auto-tune* dial one (conflict floor from judged history).
- - **v0.7.3** (2026-07-28): *retired means retired* — supersession retires from any edge path; archived hidden by default; per-graph pane state; cold-start + preset picker.
- - **v0.7.2** (2026-07-27): *eval harness born* (invented-subject corpus, arms, ladder); search retune (keyword 0.15 + reranker VOTES); mobilebert NLI swap; check_claim confidence gate; real-graph suspect eval.
- - **v0.7.1** (2026-07-25): *timeline release* — feed view + lenses, graph↔feed sync, control kit, `set_version` auto-enable, CHANGELOG convention born.
- - **v0.7.0** (2026-07-23): *customization* — per-graph GraphConfig (ontology/policy/brief), redactor UI + presets, generated skills, version tracking, handoff tag, file-read match hook, session-boundary validation, tepin auto-migrate.
- - **v0.6.x** (2026-07-20..22): *Store trait + TepinDB cutover*, model selection + hot-swap, MCP streamable-HTTP transport, machine hub + convergent serve + per-project MCP, multi-project federation + home graph, conflict push, claim search, CORS allowlist, docs/ split.
- - **v0.5.x** (2026-07-13): *local cortex* — reranker precision layer, NLI logic layer + co-reference caveat, Checkup panel, digest skill.
- - **v0.4.x** (2026-07-11/12): *rename to engram-alpha*, doctor, bulk MCP tools, full-field retrieval index, **trust v2** (time/exposure don't validate; confirmed_at; pin; demotion via judged conflicts), write-verdict protocol.
- - **v0.3.0** (2026-07-10): plugin + marketplace, audit journal, session-brief hook, drift scan, timeline, four layouts, skill overhaul.
- - **Phase 0–1** (2026-07-02..06): core graph + hybrid RAG + pane CRUD, conflict scan + suspects, decay pass, brief.
+ ## Chronicle (one line per release — `search` with `during_version` or read CHANGELOG.md for the story)
+ - **0.9.9** (OPEN 2026-09-24) — contradictions propagate along inheriting edges (`inherits` verb role, hint `inherited`); Laya int4 / multilingual selectable judges (tasksource stays default; exports at huggingface.co/techtheist/laya-onnx); `eval --shapes`; brief gains Current cycle + `bodies` / `canon_order`; numeric MCP args accept strings; the Claude Code plugin ships its MCP server (`mcp --wired-only`, rung `unwired`); sweeps release the engine lock per node (a Laya sweep froze the core); this file slimmed (old chronicle in git history).
+ - **0.9.8** (released) — unbound sessions refuse writes (issue #11); `GET /guide` operator's manual.
+ - **0.9.7** — the icon arrives; plugins say "Engram Alpha".
+ - **0.9.6** — the bench spoke lowercase: subject guard v3, clause read, tombstone title channel, duplicate guard (KnowledgeDrift v2 816 @500).
+ - **0.9.5** — KnowledgeDrift born (own repo since); title-NLI nomination path.
+ - **0.9.4** — ForgetEval + rake test; hits carry the tombstone role; knee cliff refuses 0.
+ - **0.9.3** — the pane fits any width.
+ - **0.9.2** — tombstones guard the write path.
+ - **0.9.1** — SelectMenu, Bob hooks, screenshot pipeline, docs sweep.
+ - **0.9.0** — Tombstone type, custom fields, at-rest encryption.
+ - **0.8.13** — identity-checked engine cache, honest stop, version handshake; schemas teach.
+ - **0.8.11** — `brief(project)` binds; Windsurf + Devin wiring. **0.8.10** — session-diverse delivery. **0.8.9** — set_project, NLI scoreboard.
+ - **0.8.8** — one heavy core, light bridges, binding ladder. **0.8.7** — search learns time. **0.8.6** — dual JetBrains artifacts, update awareness. **0.8.5** — first field reports. **0.8.4** — the history layer. **0.8.3** — batch width 2, fp32 embedder. **0.8.2** — merge_nodes, LongMemEval, chains. **0.8.1** — knee trim, weak line, tasksource NLI. **0.8.0** — measured not promised.
+ - **0.7.x** — eval harness, customization, timeline. **0.6.x** — TepinDB, hub, federation. **0.5.x** — local cortex. **0.4.x** — trust v2. **0.3.0** — plugin. **Phase 0–1** — core graph.
- ## Now / next (keywords)
- **0.9.8 OPEN 2026-09-18** (graph working version 0.9.8; workspace + plugin.json bumped; v0.9.7 RELEASED 2026-09-18 at 1a42747, nine assets): the issue #11 answer is in the tree (see Chronicle), pushed at 292d90d; the first Backend CI run failed on two roots_binding tests that passed on macOS (a substring assertion satisfied only by /private/tmp canonicalization, and a 10s census window lost to the starved runner — fixed by parsed-field asserts + `CENSUS_WINDOW` 45s); `GET /guide` landed the same day; the reporter has NOT yet confirmed; reply on the issue = user action. Owed: `scripts/deploy-pane.sh` + `/mcp` reconnect so the live core (8787) gates writes; this machine's stray project "techtheist" rooted at /Users/techtheist (`~/.engram/graph.tepin`, 561 KB of Windsurf-session writes) is the user's to inspect and unregister (pane); the pane's Processes panel does not yet render the census's new `client`/`bound_by` columns. v0.9.6 RELEASED 2026-09-17 at 2c760e9; the bench repo is re-pinned at 2c760e9. 0.9.6 was the four KnowledgeDrift-v2 levers — KnowledgeDrift v2 **816 (813–818) @500 / 801 @1500**, was 739 / 718 (contradiction 46→70%, drift 44→91%, deletion 93→100%). The bench repo keeps a local `[patch]` in its git-ignored `.cargo/config.toml` during development (disable it and restore `Cargo.lock` before committing there); `scripts/deploy-pane.sh` + `/mcp` reconnect so the live core (still 0.9.4 on 8787) runs guard v3, the clause read, the tombstone title channel and the duplicate guard; the `historical` tier-3 trap stays the documented NLI ceiling (3 of 20 now cross the gate on the clause read); the weak line is measured structural on v2 — a better decline signal must read something other than the top score (kind-vs-type, a margin), unattempted; the authority family (pin survives supersession `00d7pleyvpjx`, endorsements barely rank `00d7plcxvpjx`, no endorsement clock `00d7plf0wpjx`) is reported beside the headline, never summed — untouched this cycle. **KnowledgeDrift v1 ladder (0.9.5 era) = 500 and 1500** (2026-09-14, receipts `2026-09-14-knowledgedrift-500-1500.*`, `…-nogate.*`, `…-{500,1500}-{langmem,mem0}.json`): engram 85% / 80% success, score 511 / 459; LangMem (LangGraph store + semantic index, `adapters/langmem.md`) 63% / 57%, score 51 / 52; Mem0 (`infer=False`, socket-guarded, `adapters/mem0.md`) 58% / 55%, score 45 / 47; rag = LangMem to the digit — three flat stores are one system; the distance is abstention, rationale (1% vs 99%), the suspect queue, resurrection, and ~2,300 vs ~280 tok/query. Adapters: `adapters/{adapter.py,run.py,table.py}`, own venvs (gitignored), scripts carry a `digest` field. **2026-09-14 confirmation runs** (receipts `2026-09-14-knowledgedrift-500-seed{2,3}.*`, `…-500-seed{2,3}-{langmem,mem0}.json`, `…-500-{twin,late}.*`): three seeds at 500 — engram 85% (84–85) score 525 (511–543), langmem = rag 63% (61–66) on every seed, mem0 59% (57–61), grep 53% (51–55); success stable to ~1 point per arm, ordering never changes, tier-3 false alarm the widest column (0.21–0.37 on 6–10 `historical` cases). **`--pollution-shape stale|twin|late`** (shape omitted from the file/digest when default, so old exports still grade): `twin` (stale sibling wears the truth's body — only value and clock differ) → engram `stale_above` 0.21→0.64, rag 0.38→0.55, grep 0.58→0.78, drift noticed 0.91→0.98, success 85→82% all in retrieval — *no ranker separates twins; the judged queue carries the family*; `late` (sibling stamped after the truth) → flat stores byte-identical, engram 0.21→0.35 — recency is a weak prior in its ranking. `adapters/table.py --seeds` pools receipts; `WRITEUP.md` is the narrative (graveyard section: similarity-as-detector, claim-text NLI, gate 0.70, attempted-only headline, multiplier floor 1). Still owed (Task `00d5c1b4q3k8`): the `historical` tier-3 trap as the documented NLI ceiling, a `collider`-style negative per family, a sibling-less drift shape; the title-NLI path needs `scripts/deploy-pane.sh` + `/mcp` reconnect before the dogfood graph runs it, and its cost in the pane's "Scan now" at 1500 notes is unmeasured (~16 ms per judged pair, ≤8 per node). search hits carry the tombstone role, the config refuses a zero knee cliff, ForgetEval + rake phase 2 receipts landed — see Chronicle. Owed this cycle: `scripts/deploy-pane.sh` + `/mcp` reconnect so the live core serves the `tombstone` flag (the adapter's role-aware reader can then read the flag instead of the type list); **rake phase 3** — score "asked instead of acting" as its own outcome, bind method-shaped `push_batch` in the oracle, replace the T2 checksum bait (never bit) with a rake the fixture's code cannot hint at, and run at a note count where a curated file should start losing (the crossover claim has no behavioural receipt yet); ForgetEval is single-seed — a `--seed` ladder before any percentage is quoted as stable; **MCP session engine rebinding** (Problem `00d3jtpkjlay`: resolve the engine per tool call or re-check StoreIdentity, plus an open-session variant of the issue-#8 wipe e2e); **session-mate hint on hits** is the one mechanism that could move `reach@5` for engram specifically — bench it, don't assume it; a per-graph weak line for tiny graphs (dial three with a register guard) is now argued by four registers; the eval-graph literature Tasks still open: hygiene ladder `00d2fbyv8k8d`, natural nulls `00d2fbzy8k8d`, retrieval mini-sweep `00d2fbz09k8d`, DreamBench-SWE + revocation harness under `00d2fbyx8k8d`, write-up `00d2fbz19k8d`. **v0.9.3 released 2026-09-09** at 93bd8a7 (all five Release jobs green; the draft-release backend job needed one `gh run rerun --failed` — `list_changed_rebinds_home_to_project` hit "core never became healthy", the starved-runner flake of Caution `00bywotv5tx7`, third symptom; graph working version 0.9.3). v0.9.2 released 2026-09-04 at 0d81c40 (all five Release jobs green, nine assets). Owed: `scripts/deploy-pane.sh` + `/mcp` reconnect so live sessions get the `tombstoned` warning; CI annotations say the Node 20 actions (checkout@v4, setup-node@v4, upload-artifact@v4, publish-vscode-extension@v2) are being forced onto Node 24 — bump before GitHub drops Node 20. v0.9.1 released 2026-09-02 (the polish cycle on top of 0.9.0's tombstones + custom fields + encryption — see Chronicle). Documentation screenshots are regenerated by `scripts/screenshots.sh` (local-only, never CI) whenever the pane changes shape, and the Pages demo is the studio: a user-visible surface missing from `frontend/demo/data/` is missing from the docs too. History-channel chat-register pricing deferred with LongMemEval to a future cycle; whether the 0.9.0 FP 0.02@1500 changes the README headline row is a re-baseline-at-next-measure question, not a one-cell edit. Machine core on 8787 — the version handshake retires older cores automatically after a deploy, but live stdio sessions still need `/mcp` reconnect. **0.8.13** answered the issue #8 lock report (identity-checked engine cache Problem `00cddnieb6xq`, honest PID-verified stop, version handshake) and issue #9 (schema/skill graspability, Problem `00cddntfb6xq`). Issues #4/#7 fixed in 0.8.11–0.8.12, #8/#9 in 0.8.13, all open until the reporter confirms (replies to the reporter = user action); issue #1 (JetBrains 2026.1.x) fixed in 0.8.6, open until the reporter confirms the `-261` artifact. Delivery-floor Problem `00b227i6tdob` stays open pending a chat-register fit (0.8.10 bake-off: neither attack shipped). `grep_history` is ABANDONED for now (don't resurrect without a field case vector search demonstrably whiffs). Unscheduled: the **LongMemEval record attempt** — Intent `00bht8iluk1h` (online half: own API feeder + Claude Code arm, GPT-4o judge, survey published runs first; switch the arm to ingest through the real history layer), history phase-2 tail Intent `00bhzbg0itqk` (episode segmentation measure-first, thinking blocks, zstd dictionary, sessions-as-timeline-blocks, retention knob), Windsurf history adapter (blocked: Cascade transcripts encrypted at rest), Developer ID signing of releases (kills both the keychain prompts and the signature-cache class). Other open threads: MCP response-note strings still uncut (last of `00c0b7rdbcs4` — `instructions` cut in 0.8.13), *Provence-class sentence pruning*, *residual oblique misses*, session quarantine, downstream-use confirmation, SHA-256 model pinning, Cursor wiring, plugin-directory publishing (user action) — the curated-store sealing decision CLOSED in 0.9.0 (the graph switch exists, default off). Windsurf support is in-tree and field-testing (default agent project is its binding rung); Kilo adapter remains fixture-only (unverified live); BobShell ingestion assumed shared-store (verify when its login works). Watch in CI: `serve_http_only_blocks_while_core_lives_and_exits_when_it_dies` flaked twice under local parallel load. **E2e suites** live in `crates/engram-cli/tests/{e2e,e2e_wiring,e2e_encryption}.rs` (shared harness `e2e_common/`, ~40s local): lifecycle journeys (issue-#8 wipe, PID-verified stop, update takeover both directions via `ENGRAM_TEST_VERSION` — one binary plays two versions, bridge-driven core replacement, serve/stop churn + concurrent-serve race) and wiring (setup output carries current-generation skills, the Devin envelope hook delivers a brief on a fresh repo, the written MCP config launches a bridge serving 26 tools with no $refs); they ride the normal backend `cargo test --workspace`.
+ ## Now
+ The brief's **Current cycle** section is the live worklist; `list_open` has everything, and the consolidated roadmap Intent `00b7jwku2hxm` holds the backlog (user actions, owed benches, unscheduled threads). Machine core on 8787; after `scripts/deploy-pane.sh`, `/mcp` reconnect.