diff --git a/memory/2026-02-25-recursive-extraction-loop-prevention-implementatio.md b/memory/2026-02-25-recursive-extraction-loop-prevention-implementatio.md new file mode 100644 index 000000000..2874b8e59 --- /dev/null +++ b/memory/2026-02-25-recursive-extraction-loop-prevention-implementatio.md @@ -0,0 +1,17 @@ +# 2026-02-25 Session Notes + +## Recursive Extraction Loop Prevention Implementation + +Nicholai implemented a multi-layer guard mechanism to prevent infinite recursive extraction loops in the Signet daemon scheduler. The scheduler spawns full Claude Code/OpenCode agent sessions that inherit the environment, which fire Signet's session-start/end hooks, triggering summary jobs and memory extraction—creating a potentially infinite, expensive loop. + +The solution uses a `SIGNET_NO_HOOKS=1` sentinel environment variable checked at four distinct layers: + +1. **CLI Hook Guard** (`packages/cli/src/cli.ts`): Added a `preAction` hook on the `hookCmd` that exits silently (exit code 0) when the sentinel is set, preventing all hook subcommands from firing in spawned contexts. + +2. **Scheduler Spawn** (`packages/daemon/src/scheduler/spawn.ts`): Injects `SIGNET_NO_HOOKS: "1"` into the child process environment when spawning agents, ensuring spawned processes inherit the sentinel. + +3. **Pipeline Provider** (`packages/daemon/src/pipeline/provider.ts`): Adds `SIGNET_NO_HOOKS: "1"` to the ClaudeCodeProvider's child environment alongside existing `CLAUDECODE` stripping as belt-and-suspenders defense. + +4. **Daemon HTTP Guard** (`packages/daemon/src/daemon.ts`): Added an `isInternalCall()` helper that checks for `x-signet-no-hooks: 1` header, with early returns on hook routes (`/api/hooks/session-start`, `/api/hooks/user-prompt-submit`, `/api/hooks/session-end`) to guard against direct HTTP API calls bypassing the CLI. + +The implementation is non-breaking: normal user sessions are unaffected (env var not set), existing safe code paths remain unchanged, and no schema/API changes are introduced. Verification includes build/typecheck/test validation plus manual testing of the hook suppression behavior and daemon logging. \ No newline at end of file diff --git a/memory/memories.db-wal b/memory/memories.db-wal index c104adeb1..c03afaec1 100644 Binary files a/memory/memories.db-wal and b/memory/memories.db-wal differ