Skip to content

fix(classifier): stop the claude -p recursion fork bomb (0.13.1)#26

Merged
Shahinyanm merged 2 commits into
mainfrom
fix/classifier-hook-recursion
Jun 12, 2026
Merged

fix(classifier): stop the claude -p recursion fork bomb (0.13.1)#26
Shahinyanm merged 2 commits into
mainfrom
fix/classifier-hook-recursion

Conversation

@Shahinyanm

Copy link
Copy Markdown
Member

Problem

The ingest-hook recursion guard checked TJ_IN_CLASSIFIER, but no spawn site ever set it. Every classifier claude -p is a full Claude Code instance, so on startup it re-ran the user's SessionStart hooks — including task-journal ingest-hook, which spawned another classifier claude -p, and so on: an unbounded fork bomb. On a machine with git-touching SessionStart hooks (or an agent multiplexer like aimux) it also hammered git — dozens of concurrent git pull origin HEAD and stray auto-commits to main.

Fix

  • Both runners now stamp TJ_IN_CLASSIFIER=1 on the spawned claude via a shared base_claude_command.
  • The guard and the worker's env_remove reference one tj_core constant (IN_CLASSIFIER_ENV) so the setter and checker can't drift again — drift is exactly what let this through.
  • Regression test asserts the spawned command carries the marker (via Command::get_envs(), no real claude). The missing wiring had no test; now it does.

Verification

  • cargo fmt --all --check clean; cargo clippy --workspace --all-targets clean
  • cargo test -p task-journal-core agent_sdk 10/10 (incl. new base_command_carries_recursion_marker)
  • existing ingest_hook_short_circuits_when_in_classifier_env_set still green

Release

Bundles 0.13.1: this fix + the previously-merged dream agent-sdk backend (which shipped to main after 0.13.0 was tagged). Built in an isolated worktree.

🤖 Generated with Claude Code

The ingest-hook recursion guard checked TJ_IN_CLASSIFIER, but no spawn
site ever set it — so every classifier `claude -p` (a full Claude Code
instance) re-ran the user's SessionStart hooks, including ingest-hook,
which spawned another classifier `claude -p`… an unbounded fork bomb.
On a machine with git-touching SessionStart hooks (or aimux) this also
hammered git (dozens of concurrent `git pull origin HEAD`, stray commits
to main).

- Both runners now set TJ_IN_CLASSIFIER=1 via a shared base_claude_command.
- Guard + worker env_remove now reference one tj_core constant
  (IN_CLASSIFIER_ENV) so the setter and checker can't drift again.
- Regression test asserts the spawned command carries the marker — the
  missing wiring that had no test is exactly what let the bomb through.

cargo test -p task-journal-core agent_sdk: 10/10; cli ingest guard green.
@Shahinyanm Shahinyanm merged commit 6bb0a39 into main Jun 12, 2026
7 checks passed
@Shahinyanm Shahinyanm deleted the fix/classifier-hook-recursion branch June 12, 2026 05:08
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