feat(hooks): hooks.ignore_paths config to exempt project dirs from capture - #1994
feat(hooks): hooks.ignore_paths config to exempt project dirs from capture#1994JasonAiassist wants to merge 2 commits into
Conversation
…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
left a comment
There was a problem hiding this comment.
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.
|
Adding to the substring problem above: the prefix check has a Windows gap as well. With Separate from the feature itself: the diff also carries the writer-lease rework from #1966, with |
|
Thanks for this contribution, and apologies for the slow turnaround.
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. |
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_pathsconfig lets an operator exempt listed project directories from capture entirely:transcript_pathdash-encoded fallback for hooks that receive no cwd.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 todevelop, this PR reduces to the singlefeat(hooks)commit. Happy to rebase instead if you'd prefer.🤖 Generated with Claude Code