Pin spawned Claude Code CLI to compiled-in feature-gate defaults - #957
Open
jhampton wants to merge 1 commit into
Open
Pin spawned Claude Code CLI to compiled-in feature-gate defaults#957jhampton wants to merge 1 commit into
jhampton wants to merge 1 commit into
Conversation
Whether a Task subagent launches synchronously (blocking) or asynchronously (fire-and-forget) is controlled by a remote GrowthBook feature gate (tengu_amber_heron, compiled default off). When that gate flips on, subagents launch async by default even when run_in_background was never set. Async launches live inside the SDK subprocess and are torn down when it is disposed, and callers that track only explicitly-backgrounded tasks never see them — so subprocess behavior can change mid-flight purely from remote config, with no code or version change. Set DISABLE_GROWTHBOOK in buildClaudeSubprocessEnv() so the spawned CLI resolves every gate to its compiled-in default. This makes subprocess behavior reproducible and independent of remote config. Explicit run_in_background: true still works, unlike CLAUDE_CODE_DISABLE_BACKGROUND_TASKS which removes the parameter entirely. An existing DISABLE_GROWTHBOOK value is respected. Co-Authored-By: Craft Agent <agents-noreply@craft.do>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The spawned Claude Code CLI resolves feature gates through a remote GrowthBook config. One of those gates (
tengu_amber_heron, compiled default off) controls whether a Task subagent launches synchronously (blocking until the child finishes) or asynchronously (fire-and-forget).The launch decision reduces to:
When that remote gate flips on, subagents launch async by default even when
run_in_backgroundwas never set. Async launches live inside the SDK subprocess and are torn down when it is disposed/recreated, and callers that only track explicitly backgrounded tasks never see them. The net effect: spawned-CLI behavior can change mid-flight — between two runs of the same code, same CLI version — purely because a remote flag was toggled. That is a reproducibility hazard for any host that relies on blocking subagent semantics.Fix
Set
DISABLE_GROWTHBOOKinbuildClaudeSubprocessEnv()so the spawned CLI resolves every feature gate to its compiled-in default. Behavior becomes deterministic and independent of remote config; the async-launch gate stays at its compiled default (off) and cannot silently flip.Notes:
run_in_background: truestill works — this only pins the default. It is deliberately narrower thanCLAUDE_CODE_DISABLE_BACKGROUND_TASKS, which removes therun_in_backgroundparameter from the tool schemas entirely.DISABLE_GROWTHBOOKvalue (from the environment orenvOverrides) is respected, so operators can opt back into remote gates.Test plan
Adds
packages/shared/tests/claude-subprocess-feature-gates.test.ts:pins DISABLE_GROWTHBOOK=1 so feature gates resolve to compiled defaults.respects a DISABLE_GROWTHBOOK value already present in the environment.respects a DISABLE_GROWTHBOOK value passed via envOverrides.Validation:
bun test tests/claude-subprocess-feature-gates.test.tsinpackages/shared→ 3 pass, 0 fail.tsc --noEmitonpackages/shared→ 0 errors.