all-external-execution-is-subprocess-isolated
IN derived (depth 2)
All LLM-facing operations execute through subprocess isolation with environment scrubbing: derive shells out to CLI binaries rather than importing SDKs (achieving provider agnosticism), and both derive and ask independently strip the CLAUDECODE environment variable (preventing recursive invocation) — two independent safety goals achieved through the same architectural choice.
Summary
When the system needs an LLM to do work, it always runs a separate process rather than calling a library directly. This serves two purposes at once: it avoids being locked into any single AI provider's SDK, and it scrubs environment variables that could cause the subprocess to accidentally re-enter Claude Code in an infinite loop.
Justifications
SL — Subprocess execution simultaneously achieves provider agnosticism and recursion prevention
Antecedents (all must be IN):
- derive-uses-subprocess-not-sdk — The derive command invokes LLMs by shelling out to `claude` or `gemini` CLI binaries via `asyncio.create_subprocess_exec`, not through any Python SDK.
- llm-subprocess-isolation-prevents-recursion — All LLM subprocess invocations strip the CLAUDECODE environment variable to prevent recursive Claude Code entry, enforced centrally in invoke_model() and inherited by all LLM-facing modules (ask, derive, review).
Dependents
These beliefs depend on this one:
- llm-integration-is-defense-in-depth-across-layers — All LLM integration achieves defense-in-depth across two independent layers: application-level defensive bounding provides iteration caps, fail-soft error handling, Jaccard retraction guards, and hallucination filtering across all LLM-facing operations, while infrastructure-level process isolation executes all LLM calls through subprocess boundaries with CLAUDECODE environment scrubbing to prevent recursive invocation — ensuring safety at both the semantic and process boundaries.