Mnestra Changelog
Changelog
Section titled “Changelog”All notable changes to Mnestra will be documented in this file.
The format is based on Keep a Changelog.
Planned
Section titled “Planned”- Web viewer UI for browsing memories (port 37777), matching the shape
claude-memships. - Claude Code lifecycle-hooks capture path — auto-ingest tool usage without a client call.
[0.2.1] - 2026-04-19
Section titled “[0.2.1] - 2026-04-19”~/.termdeck/secrets.envfallback formnestra serve. WhenSUPABASE_URLis not set in the environment, theservesubcommand now parses~/.termdeck/secrets.env(dotenv-styleKEY=valuelines, with#comments and optional surrounding quotes) and populatesprocess.envfor any keys that aren’t already set. Existing env vars are never overridden; missing file is a silent no-op. Eliminates the #1 recurring startup friction: starting Mnestra without sourcing secrets first. Only theservepath is affected — the default stdio MCP server,export,import,--help, and--versionare unchanged.
0.2.0 - 2026-04-13
Section titled “0.2.0 - 2026-04-13”mnestra --help/--version/helpsubcommand. CLI now prints a human-readable usage block listingserve,export,import, and required environment variables, and reports the package version frompackage.json.memory_status_aggregationSQL function (migrations/006_memory_status_rpc.sql). Pushes the status histogram GROUP BY into Postgres somemoryStatus()no longer hits PostgREST’s default 1000-row cap when streaming rows to the client. The JS side now calls the RPC first and falls back to the legacy client-side aggregation (with a one-time warning) when the migration hasn’t been applied yet. Fixes the Sprint 1 observation whereby_projectsummed to ~1000 despitetotal_activebeing 3,397.- Unit tests for
memoryStatus().tests/status.test.tsdrivesmemoryStatus()with an injected fake Supabase client and asserts (a) the RPC result is unpacked correctly, (b) bigints-as-strings from Postgres are normalized to numbers, and (c) the legacy fallback path still returns a correctly summed histogram.memoryStatus()grew an optionalclientparameter for test injection; default behavior unchanged. - HTTP webhook server (
mnestra serve). A tinynode:httpsurface onMNESTRA_WEBHOOK_PORT(default37778) exposing:POST /mnestrawith{ op, ...args }forremember/recall/search/status/index/timeline/get.GET /healthz— liveness plus{ version, store: { rows, last_write } }.GET /observation/:id— single memory by UUID, same row shape asmemory_get(the citation endpoint). The MCP stdio server keeps working unchanged; the two are additive. Graceful shutdown on SIGTERM/SIGINT. Implemented insrc/webhook-server.tswith a testabledispatchOp()that takes injectable deps.
- Three-layer progressive-disclosure search:
memory_index/memory_timeline/memory_get. Exposed both as MCP tools and through the webhook server.memory_indexreturns a compact 80–120-token shape ({id, snippet≤120, source_type, project, created_at});memory_timelinereturns the same compact shape chronologically surrounding either a query hit or an explicit UUID with windows1h/24h/7d;memory_getbatch-fetches full rows (1–100 UUIDs per call) and shares its row shape withGET /observation/:id. Implemented insrc/layered.ts. - Privacy tags.
memory_remembernow strips<private>…</private>blocks from content before embedding, dedup, and insert, replacing each block with[redacted]. Rows that had any redaction getmetadata.had_private_content = true. Handles nested tags (collapse to one outer block), unclosed tags (preserved verbatim — fail-safe, never leak), case-insensitive tag matching, and attributes on the opening tag. The consolidation job re-applies the redactor defensively to every cluster member and to the canonical output so legacy rows are covered. Implemented insrc/privacy.ts; documented indocs/SOURCE-TYPES.md. mnestra export/mnestra importCLI. Streaming JSONL dump and load with no in-memory accumulation.mnestra export --project <name> --since <iso>paginates throughmemory_items500 rows at a time and writes one JSON object per line to stdout, including theembeddingcolumn so re-imports don’t need to re-embed.mnestra import < dump.jsonlreads stdin line-by-line, skips existing IDs, computes missing embeddings, and inserts. Preservesid,created_at,updated_at,is_active,archived,superseded_bywhen present. Implemented insrc/export-import.ts.
match_countcap onmemory_hybrid_search. Default cap 200, configurable via a PG setting:SET mnestra.max_match_count = 500(per-session) orALTER DATABASE … SET mnestra.max_match_count = 500(persistent). The function was previously unbounded.memory_hybrid_search_explain. New SQL function returningEXPLAIN (ANALYZE, BUFFERS)output for the equivalentmemory_hybrid_searchcall. Used by admin tooling (mnestra diagnose) to debug slow recall queries on large stores.- Unit test infrastructure. New
tsconfig.tests.json+npm testscript (tsc -p tsconfig.tests.json && node --test 'dist-tests/tests/**/*.test.js'). 21node:testcases across webhook dispatch, three-layer round-trip, privacy redaction edge cases, and error handling. No new runtime dependencies —node:http,node:readline, andnode:testare built in.
Changed
Section titled “Changed”POST /mnestrawith malformed JSON returns 400, not 500.readJsonBodynow throws a taggedHttpError(400, 'invalid JSON body')which the outer handler honours. New integration test boots the webhook server on port 0 and POSTs"not json"to assert the 400. Other thrown errors still default to 500.memory_getnow SELECTs an explicit column list (noembedding) so its row shape exactly matchesGET /observation/:id. Embeddings were never useful for citation callers and inflated responses by ~6 KB each.README.mdtool reference table updated to list all nine MCP tools and the new HTTP surface.migrations/003_mnestra_event_webhook.sqlstays as a placeholder — the webhook implementation lives in-process (src/webhook-server.ts), not in SQL.migrations/004_mnestra_match_count_cap_and_explain.sqlis the new file.
0.1.0 - 2026-04-11
Section titled “0.1.0 - 2026-04-11”- Six MCP tools:
memory_remember,memory_recall,memory_search,memory_forget,memory_status,memory_summarize_session memory_items,memory_sessions,memory_relationshipsschema with vector(1536) and HNSW indexingmemory_hybrid_searchSQL function with reciprocal rank fusion over full-text + semantic searchconsolidateMemoriesbackground job for clustering and merging near-duplicates via Claude Haiku- Programmatic API at
@jhizzard/mnestrafor embedding Mnestra inside other Node tools - Migrations split into three numbered files for clean upgrade history
- Full documentation:
README.md,docs/SCHEMA.md,docs/SOURCE-TYPES.md,docs/INTEGRATION.md,docs/RAG-FIXES-APPLIED.md
Fixed (the six RAG fixes from RAG-MEMORY-IMPROVEMENTS-AND-TERMDECK-STRATEGY.md)
Section titled “Fixed (the six RAG fixes from RAG-MEMORY-IMPROVEMENTS-AND-TERMDECK-STRATEGY.md)”- Fix 1 — Tiered recency decay by source_type.
memory_hybrid_searchnow applies aCASE source_typedecay, with one-year half-life for decisions / architecture / preferences, 90 days for facts, 30 days for bug fixes, 14 days for session summaries and document chunks. Implemented inmigrations/002_mnestra_search_function.sql. - Fix 2 — Minimum result count in
memory_recall.memoryRecallalways returns at leastmin_results(default 5) hits when that many exist, regardless of token budget or score threshold. Implemented insrc/recall.ts. - Fix 3 — Source-type weighting inside the SQL function. Decisions get a 1.5x multiplier, architecture 1.4x, bug fixes 1.3x, preferences 1.2x, document chunks 0.6x. Applied before
LIMITso important memories survive truncation. Implemented inmigrations/002_mnestra_search_function.sql. - Fix 4 — Memory consolidation background job + looser dedup threshold. New
consolidateMemoriesfunction clusters memories at >0.85 similarity and merges them via Haiku. Dedup threshold inmemoryRememberlowered from 0.92 to 0.88. Implemented insrc/consolidate.tsandsrc/remember.ts. - Fix 5 — Project affinity scoring. Exact project match multiplies score by 1.5x, the special
globalproject by 1.0x, and unrelated projects by 0.7x. Implemented inmigrations/002_mnestra_search_function.sql. - Fix 6 — Real-time event ingestion path documented.
migrations/003_mnestra_event_webhook.sqlis a placeholder marker; the live ingestion endpoint will live in the MCP server process. Documented indocs/RAG-FIXES-APPLIED.md.