Commit Graph

273 Commits

Author SHA1 Message Date
Ben Sigman 122a5fdf35 Merge pull request #762 from MemPalace/release/3.2.0
release: v3.2.0
2026-04-12 23:50:50 -07:00
Igor Lins e Silva 2a5694073d Merge pull request #764 from MemPalace/sync/main-into-release-3.2.0
sync: merge main into release/3.2.0 (preserve history)
2026-04-13 03:47:49 -03:00
Igor Lins e Silva 7a93ede797 merge: bring main's #666, #690 into release/3.2.0 (preserving history)
# Conflicts:
#	CONTRIBUTING.md
2026-04-13 03:46:21 -03:00
Igor Lins e Silva 8b26bf2ac3 chore: sync main hotfixes into release/3.2.0 (#763)
* fix: disambiguate hook block reasons to name MemPalace explicitly (#666)

Replace "your memory system" with explicit MemPalace references and
tool names (mempalace_diary_write, mempalace_add_drawer, mempalace_kg_add)
in stop and precompact hook block reasons. This prevents Claude Code from
misinterpreting the hook as a native auto-memory save instruction.

Updated in both Python (hooks_cli.py) and standalone shell scripts.

Also fix CONTRIBUTING.md Getting Started to show the fork-first workflow,
matching the PR Guidelines section.

* fix: remove chromadb <0.7 upper bound — blocks 1.x installs

The current constraint `chromadb>=0.5.0,<0.7` forces pip to install
chromadb 0.6.x, but palaces created with chromadb 1.x (which is what
the mempalace dev environment actually uses — 1.5.7 per uv.lock) have
an incompatible SQLite schema. Specifically, chromadb 0.6.x fails with
`KeyError: '_type'` when opening a collection written by 1.x.

This means a fresh `pip install mempalace` gives users a chromadb
version that cannot read palaces created in the maintainer's own
environment. The fix removes the upper bound so pip can resolve to the
current stable chromadb release.

Reproduction:
  python3 -m venv .venv && source .venv/bin/activate
  pip install mempalace          # installs chromadb 0.6.3
  # Try opening a palace created with chromadb 1.x:
  # -> _get_collection() returns None, tool_status() returns "No palace found"
  pip install chromadb==1.5.7    # force upgrade
  # -> tool_status() returns real data (26k drawers in our case)

---------

Co-authored-by: z3tz3r0 <kittipan.wang@gmail.com>
Co-authored-by: AlyciaBHZ <50111876+AlyciaBHZ@users.noreply.github.com>
Co-authored-by: Ben Sigman <1872138+bensig@users.noreply.github.com>
2026-04-12 23:44:22 -07:00
Igor Lins e Silva 81dc977bbf release: finalize v3.2.0 — version consistency + CHANGELOG
PR #761 bumped pyproject.toml to 3.2.0 but missed three other version strings,
causing test_version_consistency to fail on develop CI (macos, linux 3.11, windows).

- mempalace/version.py: 3.1.0 → 3.2.0 (unblocks test_version_consistency)
- README.md: version badge shield 3.1.0 → 3.2.0
- integrations/openclaw/SKILL.md: 3.1.0 → 3.2.0
- CHANGELOG.md: rename [Unreleased] → [3.2.0] — 2026-04-13, add entries
  for #685, #690, #707, #716, #734, #755, #757, #761

Verified locally: 689/689 tests pass, ruff clean.
2026-04-13 03:30:29 -03:00
Igor Lins e Silva 6614b9b4e7 bump version v3.2.0 (#761) 2026-04-13 03:21:50 -03:00
Mikhail Valentsev a2432a3245 fix: parse Claude.ai privacy export with messages key and sender field (#677) (#685)
* fix: parse Claude.ai privacy export with messages key and sender field (#677)

The privacy-export branch in _try_claude_ai_json only checked for the
"chat_messages" key, missing exports that use "messages" instead.  It
also only read the "role" field while real privacy exports use "sender".
Both gaps caused the file to fall through to plain-text, producing a
single giant drawer.

Changes:
- Accept "messages" alongside "chat_messages" in the conversation-object
  guard and inner extraction.
- Accept "sender" alongside "role" as the author field.
- Fall back to a top-level "text" key when content blocks are empty.
- Produce one transcript per conversation instead of concatenating all
  conversations into a single blob.
- Extract shared logic into _collect_claude_messages helper.
- Add 6 regression tests covering each variant.

* style: apply ruff format to normalize.py

* fix: guard against null text field in Claude.ai export parsing

item.get("text", "").strip() crashes when "text" is explicitly null
in the JSON (legal and observed in some exports). Use
(item.get("text") or "").strip() and add a regression test.

---------

Co-authored-by: Igor Lins e Silva <4753812+igorls@users.noreply.github.com>
2026-04-13 02:11:03 -03:00
Igor Lins e Silva e200ce2c8a fix: detect mtime changes in _get_client to prevent stale HNSW index (#757)
When external tools write to the palace database (CLI mining, scripts), the MCP server's cached ChromaDB collection becomes stale — its HNSW index doesn't know about new vectors. Develop already invalidates on inode changes (catches rebuilds) but not on mtime changes (misses in-place writes).

This PR:
- Adds st_mtime tracking alongside st_ino in _get_client; invalidates the cached client on either change.
- Adds the mempalace_reconnect MCP tool for explicit cache flush.

Original author: @jphein (#663). Original approval: @Ari4ka.
Skips test_missing_db_invalidates_cache on Windows (ChromaDB holds chroma.sqlite3 open).
2026-04-13 01:53:13 -03:00
Igor Lins e Silva 39e1651af3 fix: correct typo in entity_detector interactive classification prompt (#755)
'(r)roject' had a duplicate 'r', making it read as '(r)roject'
instead of the intended '(r)project'.

Small UX fix — no behavior change.

Co-authored-by: Arnold Wender <arnold.wender@gmail.com>
2026-04-13 01:43:57 -03:00
clach04 c17cf079ad fix #733: diagram misaligned (#734)
Converted to 7-bit clean us-ascii, which also aligns diagram.
Moved "hall" connection to be inline with Rooms in diagram.
2026-04-13 01:43:01 -03:00
shafdev f4226047cb fix: hash full content in tool_add_drawer drawer ID (#716)
* fix: hash full content in tool_add_drawer drawer ID

* style: apply ruff format

* style: fix ruff format for CI ruff 0.4.x
2026-04-13 01:40:46 -03:00
Sanjay Ramadugu 3a50966766 fix: remove 10k drawer cap from status display (#603) (#707) 2026-04-12 21:22:39 -07:00
Igor Lins e Silva e9a706aa4a Merge pull request #690 from AlyciaBHZ/fix/chromadb-version-constraint
fix: remove chromadb <0.7 upper bound — blocks 1.x installs
2026-04-13 01:13:58 -03:00
Milla J e6d232f538 docs: add CHANGELOG.md covering v3.0.0 through v3.2.0-dev (#752)
Full changelog from git history and merged PRs:
- v3.0.0 (2026-04-06): initial public release
- v3.1.0 (2026-04-09): 80+ commits, security hardening, Windows compat, tests 20→92
- Unreleased/v3.2.0: 50+ commits, i18n, backend seam, migrate command, more security

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:04:31 -07:00
Igor Lins e Silva 41b8601d86 Merge pull request #739 from MemPalace/copilot/fix-unauthorized-data-deletion
Harden palace deletion, WAL redaction, and MCP search input handling
2026-04-12 23:13:56 -03:00
Igor Lins e Silva c68370609d fix: address Copilot review comments on PR #739
- query_sanitizer: require matching quote pair in _strip_wrapping_quotes
- query_sanitizer: re-check MIN_QUERY_LENGTH after trim in tail_sentence path
- migrate: neutral confirmation message accurate for both migrate and repair
- cli: os.path.normpath instead of rstrip to handle '/' root edge case
2026-04-12 23:07:46 -03:00
Igor Lins e Silva 22328540e1 style: ruff format 2026-04-12 22:20:27 -03:00
copilot-swe-agent[bot] c383523768 chore: clarify security guardrails
Agent-Logs-Url: https://github.com/MemPalace/mempalace/sessions/775f2fc4-3051-462e-8586-6d694b55da0d

Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
2026-04-12 22:19:58 -03:00
copilot-swe-agent[bot] b1a676fa24 fix: make quote trimming explicit
Agent-Logs-Url: https://github.com/MemPalace/mempalace/sessions/775f2fc4-3051-462e-8586-6d694b55da0d

Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
2026-04-12 22:19:58 -03:00
copilot-swe-agent[bot] 976289aa5c fix: refine security validation messaging
Agent-Logs-Url: https://github.com/MemPalace/mempalace/sessions/775f2fc4-3051-462e-8586-6d694b55da0d

Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
2026-04-12 22:19:58 -03:00
copilot-swe-agent[bot] 248ecd98f1 fix: polish sanitizer and repair messaging
Agent-Logs-Url: https://github.com/MemPalace/mempalace/sessions/775f2fc4-3051-462e-8586-6d694b55da0d

Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
2026-04-12 22:19:58 -03:00
copilot-swe-agent[bot] d2d4e62543 test: expand security regression coverage
Agent-Logs-Url: https://github.com/MemPalace/mempalace/sessions/775f2fc4-3051-462e-8586-6d694b55da0d

Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
2026-04-12 22:19:58 -03:00
copilot-swe-agent[bot] c478dfa173 fix: harden palace security checks
Agent-Logs-Url: https://github.com/MemPalace/mempalace/sessions/775f2fc4-3051-462e-8586-6d694b55da0d

Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
2026-04-12 22:19:58 -03:00
copilot-swe-agent[bot] bb577bb41f Initial plan 2026-04-12 22:19:58 -03:00
Ben Sigman 5ac600b3bb style: ruff format convo_miner.py (#741) 2026-04-12 16:34:16 -07:00
Igor Lins e Silva 3b77624f8a Merge pull request #718 from MemPalace/feature/i18n
feat: i18n support — 8 languages for MemPalace
2026-04-12 20:08:59 -03:00
Ben Sigman 8efd4e53b5 docs: add CLAUDE.md + mission/principles to AGENTS.md (#720)
* docs: add CLAUDE.md + mission/principles to AGENTS.md

Add project mission, design principles, and contribution guidelines
to CLAUDE.md (new file) and prepend them to AGENTS.md.

Six non-negotiable principles: verbatim always, incremental only,
entity-first, local-first zero API, performance budgets, privacy
by architecture.

* docs: update CLAUDE.md with Milla's edits, add MISSION.md, symlink AGENTS.md

CLAUDE.md:
- Add Zettelkasten + AAAK explanation to mission (Milla's edit)
- Add 7th principle: background everything
- Update project structure to match current develop (all modules)
- Fix hooks listing to match actual public repo
- Add backends/ to structure and key files

MISSION.md:
- Milla's personal narrative on why MemPalace exists
- Origin story, AAAK inside joke, v4 goals

AGENTS.md:
- Now symlinks to CLAUDE.md (single source of truth)

* docs: trim MISSION.md — remove v4 notes and workflow (moved to private)
2026-04-12 15:28:01 -07:00
Ben Sigman 6f1cf6c86e Merge branch 'main' into fix/chromadb-version-constraint 2026-04-12 14:29:43 -07:00
Mikhail Valentsev 87e8bafad8 fix: prevent convo_miner from re-processing 0-chunk files on every run (#654) (#732)
* fix: register 0-chunk files to prevent re-processing on every mine (#654)

mine_convos() has three early-exit paths (OSError, content too short,
zero chunks) that skip writing anything to ChromaDB. Since
file_already_mined() checks for the presence of a document with a
matching source_file, these files are re-read and re-processed on
every subsequent run.

Add _register_file() that upserts a lightweight sentinel document
(room="_registry", ingest_mode="registry") so file_already_mined()
returns True on future runs.

Note: Bug 2 from the issue (drawers_added counter always 0) was
already resolved upstream via the switch from collection.add() to
collection.upsert().

* fix: resolve macOS path symlink in test + remove unused variable
2026-04-12 14:25:34 -07:00
Sanjay Ramadugu 9b60c6edd7 fix: remove 8-line AI response truncation in convo_miner (#692) (#708)
The _chunk_by_exchange() function was silently truncating AI responses
to 8 lines via ai_lines[:8]. Any content beyond line 8 was discarded,
violating the project's verbatim storage principle.

Now the full AI response is preserved. When a combined exchange exceeds
CHUNK_SIZE (800 chars, aligned with miner.py), it is split across
consecutive drawers instead of being truncated.
2026-04-12 14:23:57 -07:00
shafdev d52d6c9622 fix: store full AI response in convo_miner exchange chunking (#695) 2026-04-12 14:23:52 -07:00
Mikhail Valentsev 091c2fe1c6 fix: mine --dry-run TypeError on files with room=None (#586) (#687)
* fix: return "general" room from process_file error paths (#586)

process_file() returned (0, None) for already-mined, unreadable, and
too-short files.  In --dry-run mode the caller always enters the
room_counts branch, so None ended up as a dict key and crashed the
summary printer with "unsupported format string passed to
NoneType.__format__".

Returning "general" instead of None makes the function contract
explicit: it always yields (int, str).  This matches the consensus
fix discussed in the issue thread.

* style: apply ruff format to test_miner.py
2026-04-12 14:23:44 -07:00
Jeffrey Hein 862a07b198 fix: skip arg whitelist for handlers accepting **kwargs (#572) (#684)
* fix: skip arg whitelist for handlers accepting **kwargs (#572)

The schema-based argument filter (from #647) strips all kwargs not
declared in input_schema. This breaks handlers that accept **kwargs
for pass-through to ChromaDB or other backends.

Add inspect.Parameter.VAR_KEYWORD check before filtering — handlers
with **kwargs receive all arguments unfiltered.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: guard inspect.signature failure, default to filtering

Wrap inspect.signature() in try/except — on failure, default to
filtering (safe fallback). Addresses Copilot feedback on fragility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 14:23:39 -07:00
Jeffrey Hein 6e2ced3287 fix: allow Unicode in sanitize_name() — Latvian, CJK, Cyrillic (#637) (#683)
* fix: allow Unicode in sanitize_name() — Latvian, CJK, Cyrillic names (#637)

_SAFE_NAME_RE was ASCII-only ([a-zA-Z0-9]), rejecting valid Unicode
names like "Jānis" or "太郎". Changed to \w which matches Unicode
word characters (letters, digits, underscore) in Python 3.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: tighten Unicode regex, add sanitize_name tests

Use [^\W_] for first/last char to allow Unicode letters/digits but
reject leading/trailing underscores (Copilot feedback). Add 7 tests
covering Latvian, CJK, Cyrillic, path traversal, and edge cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 14:23:34 -07:00
Jeffrey Hein 915b8b2c75 fix: add --yes flag to init instructions for non-interactive use (#534) (#682)
AI agents calling `mempalace init` hang on the interactive confirmation
prompt. The --yes flag skips it, enabling automated setup.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 14:23:29 -07:00
Igor Lins e Silva c3f9b76d9a fix(ci): resolve ruff lint + format failures
- Remove unused `json` and `current_lang` imports from
  mempalace/i18n/test_i18n.py (F401)
- Reformat Dialect.__init__ signature in mempalace/dialect.py
  (ruff format collapses multi-line signature, adds blank line
  after lazy import)

Both auto-fixes from `ruff check --fix` / `ruff format`. No behavioral
changes.
2026-04-12 17:14:06 -03:00
MSL baf3c0ab64 feat: i18n support — 8 languages for MemPalace
Add language dictionaries: English, French, Korean, Japanese, Spanish,
German, Simplified Chinese, Traditional Chinese.

Each language is a single JSON file with:
- Localized terms (palace, wing, closet, drawer, etc.)
- CLI output strings with {var} interpolation
- AAAK compression instructions in that language
- Regex patterns for offline topic/quote/action extraction

Usage: Dialect(lang="ko") or set "language": "ko" in config.
Contributors can add new languages by copying en.json and translating.

Dialect class now accepts lang param and loads AAAK instruction +
regex patterns from the i18n dictionary automatically.

Tests: mempalace/i18n/test_i18n.py — all 8 languages pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 10:09:47 -07:00
Igor Lins e Silva 74e5bf6090 Merge pull request #691 from MemPalace/codex-github-pages-publishing
ci: fix github pages publishing
2026-04-12 05:57:57 -03:00
AlyciaBHZ 27d8944f5e fix: remove chromadb <0.7 upper bound — blocks 1.x installs
The current constraint `chromadb>=0.5.0,<0.7` forces pip to install
chromadb 0.6.x, but palaces created with chromadb 1.x (which is what
the mempalace dev environment actually uses — 1.5.7 per uv.lock) have
an incompatible SQLite schema. Specifically, chromadb 0.6.x fails with
`KeyError: '_type'` when opening a collection written by 1.x.

This means a fresh `pip install mempalace` gives users a chromadb
version that cannot read palaces created in the maintainer's own
environment. The fix removes the upper bound so pip can resolve to the
current stable chromadb release.

Reproduction:
  python3 -m venv .venv && source .venv/bin/activate
  pip install mempalace          # installs chromadb 0.6.3
  # Try opening a palace created with chromadb 1.x:
  # -> _get_collection() returns None, tool_status() returns "No palace found"
  pip install chromadb==1.5.7    # force upgrade
  # -> tool_status() returns real data (26k drawers in our case)
2026-04-12 16:50:18 +08:00
Igor Lins e Silva a487d059ba ci: fix github pages publishing 2026-04-12 05:19:30 -03:00
Igor Lins e Silva f224c48e09 Merge pull request #439 from igorls/docs/vitepress-site
docs: add VitePress documentation site
2026-04-12 04:55:58 -03:00
Mikhail Valentsev f56e67b516 docs: fix stale milla-jovovich org refs and branch target in contributor docs (#679)
The repo moved to the MemPalace org but several docs still point at the
old milla-jovovich URLs.  Also, CONTRIBUTING.md tells people to PR
against main while the actual workflow (per ROADMAP.md) targets develop.

Files touched:
- CONTRIBUTING.md: clone URL, issues URL, PR target branch
- examples/gemini_cli_setup.md: clone URL
- integrations/openclaw/SKILL.md: homepage and license URLs
2026-04-12 00:00:21 -07:00
travisBREAKS 89206107fa fix(bench): remove hardcoded credential paths from benchmark runners (#177)
The `_load_api_key()` function in longmemeval_bench.py and locomo_bench.py
searched for API keys in a fixed path (`~/.config/lu/keys.json`) using
personal key names (`anthropic_milla`, `anthropic_claude_code_main`).

This leaks internal infrastructure details into the public codebase and
trains contributors to store credentials in a non-standard location
rather than using the standard ANTHROPIC_API_KEY env var.

Simplified to: CLI flag > env var > empty string. Updated help text
and HYBRID_MODE.md docs to match.

Co-authored-by: Tadao <tadao@travisfixes.com>
2026-04-11 23:14:36 -07:00
Brooke Whatnall dc143471bc fix: expand ~ in split command directory argument (#361)
Path("~/foo") does not expand tilde on its own, causing
`mempalace split ~/some/dir` to silently find no files.

Fix by calling .expanduser().resolve() in both places the
path is constructed: cmd_split in cli.py (defensive, at the
CLI boundary) and main() in split_mega_files.py (the root cause).

Co-authored-by: Brooke Whatnall <brookewhatnall@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 23:14:28 -07:00
7. Sun 15d9ee1b51 fix: close KnowledgeGraph SQLite connections in test fixtures (#450)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 23:14:23 -07:00
7. Sun d82bbe754c fix: remove duplicate _client_cache/_collection_cache declarations in mcp_server.py (#449)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 23:14:18 -07:00
travisBREAKS d8b2db696f fix(bench): remove global SSL verification bypass in convomem_bench (#176)
The module-level `ssl._create_default_https_context = ssl._create_unverified_context`
disables certificate verification for ALL urllib requests in the process,
not just the benchmark's HuggingFace downloads. This silently exposes
the benchmark runner to MITM attacks.

If a specific environment needs to skip verification (e.g. corporate proxy),
users can set `PYTHONHTTPSVERIFY=0` or pass a custom ssl context per-request
rather than globally patching the ssl module.

Co-authored-by: Tadao <tadao@travisfixes.com>
2026-04-11 23:14:12 -07:00
dbshadow 007acca59a fix: ignore wait_for_previous argument from Gemini MCP clients (#322) 2026-04-11 23:14:00 -07:00
z3tz3r0 f138d4929d fix: disambiguate hook block reasons to name MemPalace explicitly (#666)
Replace "your memory system" with explicit MemPalace references and
tool names (mempalace_diary_write, mempalace_add_drawer, mempalace_kg_add)
in stop and precompact hook block reasons. This prevents Claude Code from
misinterpreting the hook as a native auto-memory save instruction.

Updated in both Python (hooks_cli.py) and standalone shell scripts.

Also fix CONTRIBUTING.md Getting Started to show the fork-first workflow,
matching the PR Guidelines section.
2026-04-11 23:06:41 -07:00
Jeffrey Hein abc99f4154 fix: auto-repair BLOB seq_ids from chromadb 0.6→1.5 migration (#664)
Note from code review: (1) silent exception swallow on migration failure means caller proceeds with potentially corrupt DB — consider returning a boolean or re-raising in a follow-up. (2) No blob length validation before int.from_bytes — malformed rows could produce wrong seq_id values. Both are edge cases; the fix is still valuable for the common chromadb 0.6→1.5 migration path.
2026-04-11 23:06:01 -07:00