Skip to content

feat: Advanced Hooks (Mirroring, Venv Pinning, KG Unification) - #1328

Closed
zhapostolski wants to merge 6 commits into
MemPalace:mainfrom
zhapostolski:feat/mirror-and-pin
Closed

feat: Advanced Hooks (Mirroring, Venv Pinning, KG Unification)#1328
zhapostolski wants to merge 6 commits into
MemPalace:mainfrom
zhapostolski:feat/mirror-and-pin

Conversation

@zhapostolski

Copy link
Copy Markdown

Enhanced hook system including:\n- Local memory mirroring (auto-replicate .md files into palace)\n- explicit venv pinning via MEMPAL_PYTHON\n- Knowledge Graph unification across all hook events\n- Automated harness detection for Gemini, Codex, etc.

Previously hook_session_start was a no-op stub. Now it:
- Parses cwd + source from the harness input
- Matches cwd basename to a known wing via tool_status()
- Builds additionalContext from MemoryStack.wake_up() + a protocol nudge
  telling the LLM to kg_query/search before responding and add_drawer/kg_add
  when making decisions
- Returns Claude-Code-compatible {hookSpecificOutput.additionalContext}
  shape; harnesses that ignore the key see a no-op

This makes SessionStart actually useful: the LLM gets ~700 tokens of
project context on every session start instead of an empty {}.

Tests: replaced the pass-through assertion with two cases (context
injected when palace resolvable, no-op when MempalaceConfig fails).
All 121 existing tests still pass.
Adds _mirror_local_memory() called from hook_stop on every fire.
Scans default memory locations (~/.claude/projects, ~/.codex/memories,
~/.gemini/memory, ~/.qwen/memory) for *.md files; for each new or
modified file, calls tool_add_drawer with wing derived from the
project slug and room from the filename stem.

Why: even with the SessionStart protocol nudge, models (notably
Claude Code) reflexively write to their per-CLI auto-memory dirs
instead of mempalace MCP tools. This makes mempalace a guaranteed
mirror of those .md files regardless of LLM cooperation.

Behavior:
- Idempotent via {path: mtime} state in ~/.mempalace/hook_state/mirror_state.json
- Skips index files (MEMORY.md, CLAUDE.md, GEMINI.md, QWEN.md, AGENTS.md)
- Skips empty files (still records mtime so we don't keep re-reading)
- Records duplicates (mempalace dedupe) as "seen" to avoid retry loops
- Wing slug parser: -home-...-projects-<wing> → <wing> (Claude convention),
  else first directory after the root
- All errors caught — never blocks the harness
- Disable via MEMPAL_MIRROR_DISABLED=1
- Override roots via MEMPAL_MIRROR_ROOTS=path:path:...

Verified: real run on 312 .md files added 248 new drawers (rest were
chromadb dupes or empty). Second run: 0 added, 312 skipped_unchanged.
All 128 tests pass (8 new mirror tests).
The save and precompact wrappers ran via bare 'python3', which resolves
to whatever interpreter is on PATH. From a CLI launched in a clean shell
(or any shell without the right venv activated), python3 is system
python — which lacks chromadb and other mempalace deps. The hooks
silently degraded: hook_session_start would no-op, and the new
_mirror_local_memory() would log
  "mirror: cannot import tool_add_drawer (No module named 'chromadb')"
and skip the entire mirror, defeating Option-2 dual-write.

Fix: each wrapper now resolves $MEMPAL_PYTHON, defaulting to
$HOME/.mempalace/venv/bin/python (the canonical install location), and
falls back to plain python3 if that doesn't exist. All three wrappers
(save, precompact, session-start) follow the same pattern so they
behave identically across Claude / Codex / Gemini / Qwen.

Verified end-to-end from a stripped env (env -i PATH=/usr/bin:/bin):
- save_hook returns {} cleanly with no chromadb errors in hook.log
- precompact_hook returns {"decision":"allow"}
- session_start_hook returns Claude-shape additionalContext with
  wing-matched wake-up text
@zhapostolski

Copy link
Copy Markdown
Author

Superseded by #1335 (feat/community-patches) which consolidates all hook improvements plus 28 community PR fixes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant