Skip to content

feat(hooks): hooks.ignore_paths config to exempt project dirs from capture - #1994

Open
JasonAiassist wants to merge 2 commits into
MemPalace:developfrom
JasonAiassist:fix/hooks-ignore-paths
Open

feat(hooks): hooks.ignore_paths config to exempt project dirs from capture#1994
JasonAiassist wants to merge 2 commits into
MemPalace:developfrom
JasonAiassist:fix/hooks-ignore-paths

Conversation

@JasonAiassist

Copy link
Copy Markdown

Problem

Ephemeral worker sessions (objective-loop agents spawning dozens of nested harness sessions per hour) each fire session-start/stop/session-end ingests. On my store that meant hundreds of ingest writes per hour, several of which died mid-write (segfault in the HNSW add path) and re-diverged the index within hours of a repair (same failure family as #1888 / #1966).

Change

A new hooks.ignore_paths config lets an operator exempt listed project directories from capture entirely:

  • Matched by cwd path-prefix, with a transcript_path dash-encoded fallback for hooks that receive no cwd.
  • The hook still returns valid JSON immediately for exempted paths, so the harness never sees an error.
  • 38 lines of unit tests covering prefix matching, the transcript-path fallback, and the passthrough case; full suite green (147 tests).

Running live on my instance since 2026-07-10 — the agent-farm directories no longer generate ingests, and the store has stayed convergent since.

Note

Stacked on #1966 — this branch includes that PR's commit (327c28e) because it was cut from the same local build; once #1966 merges to develop, this PR reduces to the single feat(hooks) commit. Happy to rebase instead if you'd prefer.

🤖 Generated with Claude Code

Jason-Aiassist and others added 2 commits July 8, 2026 10:22
…alace#1888)

The per-palace writer lease (MemPalace#1818/MemPalace#1823) is held for the whole MCP
process lifetime, so a single interactive session starves every other
writer on the palace — hook and manual mines exit with
MineAlreadyRunning, daemon jobs fail, and a second session's mutating
tools are refused — for hours at a time.

Release the lease once no mutating tool has run for
MEMPALACE_MCP_WRITER_LEASE_IDLE_S seconds (default 300; 0 restores the
legacy hold-until-exit behavior). The release also runs
_force_chroma_cache_reset() so the next mutating call reopens the
palace from disk: a re-acquire is only safe when no stale in-memory
HNSW state survives, which is the reason the lease was
lifetime-scoped in the first place. Re-acquisition rides the existing
self-heal retry path, so the first mutating tool after a release
transparently wins the lease back.

The idle-exit watchdog thread drives the release check and now also
starts when only the lease release is enabled. The atexit hook is
registered once and reads the current lease, replacing the
per-acquire lambda that would go stale across release/re-acquire
cycles.

Part of the MemPalace#1963 concurrent-writer cluster.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pture

Ephemeral worker sessions (objective-loop agents spawning dozens of nested
harness sessions per hour) each fire session-start/stop/session-end ingests;
on this store that meant hundreds of ingest writes per hour, several of
which died mid-write (segfault in the HNSW add path) and re-diverged the
index hours after a repair. ignore_paths lets an operator exempt those
project dirs from capture entirely: matched by cwd path-prefix with a
transcript_path dash-encoded fallback; hook still returns valid JSON.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@fatkobra fatkobra left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking:
the transcript-path fallback uses an unanchored substring check on a lossy slash-to-dash encoding. For example, ignored cwd /home/dev/foo encodes to -home-dev-foo, which also appears inside the transcript directory for sibling project /home/dev/foobar. Path components containing dashes can create additional encoding collisions. This can silently suppress capture for an unrelated project.

Please parse the known project-directory component from the transcript path and compare a complete encoded path token with explicit boundaries, using the same normalization on both sides. Add regressions for foo versus foobar and for paths whose slash/dash encodings collide.

@mvalentsev

Copy link
Copy Markdown
Contributor

Adding to the substring problem above: the prefix check has a Windows gap as well.

With ignore_paths: ["C:\\Users\\dev\\foo"], that exact directory is skipped through the cwd == p branch, but a session in C:\Users\dev\foo\sub is captured, because cwd.startswith(p + "/") never matches a backslash path. So on Windows the setting covers the top directory only and quietly misses everything under it, which is the opposite failure from the one on Linux but just as invisible. Normalizing separators on both sides and comparing whole components would take care of this and the dash-encoding case in the same place.

Separate from the feature itself: the diff also carries the writer-lease rework from #1966, with _acquire_mcp_writer_lock rewritten and _writer_lease_activity, _writer_lease_idle_seconds and the idle-release env knob added. A config knob for hook capture and a change to when the MCP process releases the palace writer lease carry very different risk, and someone reviewing by the title won't be expecting the second one.

@igorls

igorls commented Aug 15, 2026

Copy link
Copy Markdown
Member

Thanks for this contribution, and apologies for the slow turnaround.

develop has moved a fair way since this was opened and the branch no longer merges cleanly. If you're still interested in landing it, could you rebase onto current develop? Once it merges cleanly and CI is green I'll get it reviewed for the 3.8.0 cycle.

If you'd rather not pick it back up, no problem at all — just say so and I'll close it out, and thanks either way for taking the time to send it.

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.

5 participants