github MemPalace/mempalace v3.6.0

7 hours ago

v3.6.0 — secure remote serving, temporal facts, and resilient recovery

This release makes MemPalace substantially easier to operate beyond a single local process while tightening the guarantees that protect long-lived palaces. A new secure-by-default mempalace serve path supports authenticated remote and team deployments with TLS and read-only enforcement; an opt-in Milvus backend adds embedded, self-hosted, and managed storage choices; and atomic knowledge-graph supersession gives changing facts precise temporal boundaries. Conversation chronology, mined-session graph derivation, project exclusions, and LaTeX coverage deepen ingestion, while startup, metadata, and recovery work make large palaces faster and safer. The MCP surface now comprises 36 tools.

Features

  • Turnkey secure remote / team server. mempalace serve exposes the full MCP surface over HTTP with secure defaults: non-loopback binds require a bearer token, generated tokens are stored with restrictive permissions and passed through the child environment rather than argv, native TLS 1.2+ is supported, and --read-only both hides and refuses mutating tools. Docker Compose, systemd, and environment templates are included. (#1877, #1897, #1900)
  • Milvus storage backend. The new opt-in milvus backend supports Milvus Lite, self-hosted Milvus, and Zilliz Cloud, with COSINE vector search, native BM25 lexical search for new collections, namespace isolation, target-mismatch protection, and an optional dependency extra. (#1899)
  • Atomic knowledge-graph fact replacement. supersede() / mempalace_kg_supersede closes an open fact and opens its successor at one shared instant. Temporal queries use half-open intervals at timestamp precision while preserving whole-day semantics for date-only facts. (#1913)
  • Conversation chronology is preserved. Drawers retain transcript time as authored_at, search results expose it, exact hybrid-score ties prefer recently authored content, and an idempotent dry-run-first backfill updates existing palaces without re-embedding. mempalace_list_drawers also gains since / before bounds. (#1890, #1891)
  • Mined sessions populate the associative graph. A precision-biased structural extractor records code symbols, URLs, paths, and qualified identifiers as drawer entities; conversation mining derives hallways from them, exposed by the new mempalace hallways CLI command. (#1894, #1895)
  • Per-project mining exclusions through exclude_patterns in mempalace.yaml, without changing corrected --limit semantics. (#1213, #1953)
  • LaTeX project coverage for .tex and .bib prose sources. (#1901)
  • Shared daemon write-routing policy provides one consistent policy seam for routing write-capable clients toward the local daemon. (#2027)
  • Checkpoint author attribution now preserves the filing agent instead of hard-coding every checkpoint drawer as checkpoint. (#2023, #2034)

Performance

  • MCP initialization no longer waits for palace-wide integrity work. stdio answers initialize immediately while startup preflight runs in the background; concurrent tools join the same verdict instead of duplicating work. Large-palace startup SQLite probes are bounded, while repair preflights remain strict. (#1911, #1987)
  • Qdrant metadata counts use server-side facets instead of fetching and tallying every record; the embedding wrapper forwards facet and bulk-metadata capabilities correctly. (#1868, #1898)
  • pgvector metadata-only fetches omit document payloads, reducing transfer and decoding work. (#1892)

Bug Fixes

  • Chroma recovery distinguishes derived-index damage from data loss. Valid all-layer-0 HNSW segments are no longer quarantined repeatedly; isolated FTS5 corruption is rebuilt from intact content during repair and after mining; embedded NUL bytes are sanitized before reaching ChromaDB. (#1716, #1872, #1878, #1927, #1928)
  • SQLite recovery is bounded, atomic, and honest. Integrity checks wait out transient writer contention; recovery archives use atomic rename; repair --mode from-sqlite rebuilds FTS5, vacuums, and requires a clean final PRAGMA quick_check; cleanup failures return non-zero instead of printing false success. (#1945, #2015, #2017)
  • CLI search checks HNSW divergence before opening ChromaDB, routing damaged palaces directly to SQLite BM25 while leaving healthy and non-Chroma backends on their normal path. (#2016)
  • Writer leases recover instead of stranding servers read-only. Refused writers retry and promote after a peer exits; status cannot acquire the writer lease; re-entrant holders are released across interruption; checkpoint and delete_by_source are correctly classified as mutations. (#1923, #1930, #1934, #1960, #1970, #1971)
  • Status reports only checks that actually ran. Non-Chroma backends mark Chroma SQLite integrity as not applicable. (#1931, #1946)
  • Conversation transcripts are treated as mutable. Appended or rewritten sessions are purged and re-filed by modification time, while Claude Code tool-results/ sidecars are excluded from scans. (#1957, #2010)
  • Explicit palace selection scopes derived graph state so mining hallways and tunnels remain beside the selected --palace. (#2018)
  • Remote and local server hardening. Non-loopback HTTP requires a token unless explicitly overridden; provider probes cannot reuse ambient external keys before selection; hook transcript and file-copy/repair paths receive stricter validation; importing MCP no longer clobbers root logging; HTTP writes re-enter the palace lock safely; routine disconnects no longer emit tracebacks. (#1859, #1860, #1864, #1885, #2003, #2004)
  • Mining and configuration correctness. Oversized files warn visibly, configured ~ paths expand consistently, wing slugs handle special characters, and Windows background processes avoid console flashes. (#923, #1852, #1857, #1863, #1865)
  • Windows .gitignore handling uses UTF-8 explicitly, avoiding locale-dependent failures. (#1648)
  • L1 wake-up prefers the latest moments when importance ties. (#1630)
  • Backend detection requires a SQLite magic header, preventing unrelated files from being mistaken for a palace. (#1893, #1896)

Documentation

  • Added a storage-backend configuration reference, a remote/team-server deployment guide, authored_at migration guidance, and refreshed the OpenClaw integration for the full 36-tool MCP surface. (#1719, #1877, #1890, #1904, #1905)

Internal

  • Expanded WAL crash-safety, idempotence, and redaction-path coverage; updated GitHub Actions and Ruff; repaired uv.lock drift for Ruff 0.15.20 and Python 3.9 dependency markers. (#1869)

A big thank-you to everyone who contributed to this release. Contributors and first-time contributors are credited below.

What's Changed

  • fix: tighten local guards and file handling by @igorls in #1864
  • test(wal): cover WAL crash-safety, idempotent setup, and redaction edge paths by @arnoldwender in #1869
  • fix: spawn daemon with CREATE_NO_WINDOW to match hook miner (#1783) by @eldar702 in #1857
  • fix(cli): add repair rebuild-index alias by @jsiu93 in #1670
  • Fix/wing slug special chars by @tp9imka in #1852
  • fix(hooks): hide conhost window on Windows in _mine_sync non-daemon path by @davidfi01 in #1863
  • fix: expand tilde in palace_path when read from config file by @joesebastian6079 in #1865
  • fix(chroma): stop quarantining valid all-layer-0 HNSW segments (#1716) by @igorls in #1872
  • fix(repair): auto-heal isolated FTS5 inverted-index corruption (#1596) by @igorls in #1878
  • fix(mcp): stop clobbering host app root logger at import (#1860) by @mvalentsev in #1885
  • fix(layers): order L1 wake-up by recency (filed_at) so it surfaces the latest moments by @davidglidden in #1630
  • fix(cli): force UTF-8 when reading/writing .gitignore in init by @ALaDingAhmad in #1648
  • chore(deps): bump actions/checkout from 6 to 7 by @dependabot[bot] in #1882
  • chore(deps): bump docker/setup-qemu-action from 3 to 4 by @dependabot[bot] in #1880
  • chore(deps): bump docker/setup-buildx-action from 3 to 4 by @dependabot[bot] in #1881
  • chore(deps-dev): bump ruff from 0.15.18 to 0.15.20 by @dependabot[bot] in #1883
  • fix(backends): require SQLite magic header for chroma + sqlite_exact detect() (#1893) by @messelink in #1896
  • fix(pgvector): skip document column for metadata-only fetches (#1840 follow-up) by @messelink in #1892
  • feat(convo): preserve authored timestamp from transcripts by @JosefAschauer in #1890
  • fix(palace): process-wide mine_palace_lock re-entrancy so the HTTP transport can write by @trongnguyenbinh in #1859
  • feat(mcp): add since/before date filter to list_drawers (#1128) by @mvalentsev in #1891
  • feat: optimize metadata counting using Qdrant server-side facets by @Prayaksh in #1868
  • feat(graph): auto-populate the associative graph from mined sessions by @JosefAschauer in #1895
  • docs(guide): Remote / Team Server deployment guide (#1877) by @igorls in #1897
  • feat(serve): turnkey secure remote MCP server (#1877) by @igorls in #1900
  • docs(config): add storage backends configuration reference by @igorls in #1904
  • fix(docs): wide-table layout — stop clipping, fit backend table by @igorls in #1905
  • feat: add LaTeX (.tex, .bib) to readable and prose extensions by @messelink in #1901
  • docs(openclaw): catch up SKILL.md with 8 newer MCP tools by @raman325 in #1719
  • fix: read-only mode misses checkpoint and delete_by_source in _MUTATING_TOOLS by @yusefhaddad in #1930
  • fix(mine): log warning when files exceed MAX_FILE_SIZE (#923) by @mvalentsev in #924
  • fix(backends): forward facet_counts + get_all_metadata in EmbeddingCollection by @messelink in #1898
  • fix: skip startup SQLite integrity check on oversized palace (unblocks MCP handshake) by @trek-e in #1911
  • fix: sanitize embedded NUL bytes before they reach ChromaDB by @jrzmurray in #1929
  • fix: half-open as-of interval + supersede() to end KG boundary double-count by @ggettert in #1914
  • [codex] fix status writer lease classification by @igorls in #1934
  • fix(mcp): mark sqlite_integrity not-applicable on non-chroma backends (#1931) by @mvalentsev in #1946
  • fix(convo_miner): treat transcripts as mutable, not immutable by @jrzmurray in #1957
  • fix(mcp): self-heal writer lease instead of latching read-only for life by @Evgen197310 in #1960
  • fix(repair): use os.rename for in-place archive, not shutil.move by @KeilerHirsch in #1945
  • Add Milvus storage backend by @zc277584121 in #1899
  • style(tests): fix ruff format check left red by #1960 by @Evgen197310 in #1965
  • feat: add exclude_patterns config key to mempalace.yaml (rebase of #1213) by @jrzmurray in #1953
  • fix(palace): pair the mine_palace_lock holder-set update with its release (#1970) by @mvalentsev in #1971
  • fix(convo_miner): don't mine Claude Code tool-results/ dirs — raw tool dumps flood the palace by @KeilerHirsch in #2010
  • fix(mcp): answer initialize immediately — run startup preflight in a background thread by @KeilerHirsch in #1987
  • mine: auto-heal isolated FTS5 corruption instead of forcing manual repair by @jrzmurray in #1928
  • fix(mcp): don't log a traceback when an HTTP client disconnects mid-response (#2003) by @mvalentsev in #2004
  • fix(repair): wait out transient SQLite contention by @igorls in #2015
  • fix(searcher): guard CLI divergence before Chroma open by @igorls in #2016
  • fix(repair): require clean SQLite recovery finalization by @igorls in #2017
  • fix: scope derived graph state to explicit palace by @igorls in #2018
  • chore(release): 3.6.0 by @igorls in #2019
  • chore: sync main hotfixes into develop before 3.6.0 by @igorls in #2022
  • fix(mcp): preserve agent attribution in mempalace_checkpoint (#2023) by @mvalentsev in #2034
  • feat(routing): add shared daemon write-routing policy by @fatkobra in #2027
  • Release v3.6.0 — promote develop to main by @igorls in #2020

New Contributors

Full Changelog: v3.5.0...v3.6.0

Don't miss a new mempalace release

NewReleases is sending notifications on new releases.