Summary
cf-phase-runner and cf-phase-compiler are declared with isolation = true, which the generator translates to isolation: worktree for Claude Code. But a plan's authoritative state lives under {cf-studio-path}/.plans/{task-slug}/ (designed to be gitignored), and target SDLC artifacts are meant to be written in the main working tree. Worktree isolation is therefore structurally mismatched with plan execution/compilation: every meaningful write is a sandbox escape, and gitignored plan state is not even present inside the worktree.
Root cause
Worktree isolation assumes the agent's working set lives inside the worktree. For phase execution/compilation that assumption is false:
Both agents are isolation = true:
The generator unconditionally emits isolation: worktree when agent.isolation is true (agents.py#L1284, #L4588, #L5241).
Net effect: writes to the canonical (main-tree) plan dir + SDLC outputs escape the worktree sandbox, triggering per-write permission prompts; gitignored plan state is absent from the worktree entirely.
Note that the generator is already configurable per agent — isolation is a manifest field (default false, manifest.py#L82), and most write-capable agents (cf-generate-author-*, cf-generate-coder-*, the migrate-* set) are explicitly isolation = false and operate in-place. The phase agents are the remaining write-capable agents still set to isolation = true.
Proposed fixes (pick one or combine)
- Default these agents to non-worktree isolation (recommended). Set
isolation = false for cf-phase-runner and cf-phase-compiler in skills/studio/agents.toml so they operate on the gitignored plan state in the main tree. Keep worktree only where parallel code mutation is the goal (cf-codegen). Update the agents' rationale comments (currently "write access is bounded by host isolation").
- Make plan state visible in the worktree — mount/symlink
{cf-studio-path}/.plans/<task-slug>/ into the worktree, or stage plan artifacts under a non-gitignored, worktree-tracked location.
- Pre-approve known plan paths for writing inside the worktree sandbox — treat the canonical plan dir plus the plan's declared outputs as pre-approved, so no per-write prompts occur.
- Document a recommended permission allowlist for the recurring read-only commands (e.g.
validate, validate --artifact, list-ids, where-used/where-defined) and for writes under the plan dir + module docs.
How fix 1 behaves
isolation is a per-dispatch property, not a session-wide mode: the orchestrator never runs in a worktree, and only a dispatched sub-agent whose frontmatter carries isolation: worktree gets its own worktree for that one run. Sub-agents with isolation = false write directly to the main tree.
After fix 1, the only write-capable agent left in a worktree is cf-codegen — which is the legitimate use (isolated code generation from a complete spec; it never touches plan state). cf-brainstorm-expert and cf-brainstorm-panel stay isolation = true but are read-only, so the write-escape problem does not apply.
This is also not "the only way code gets written": cf-codegen is only the first-match path when a task is fully specified with no clarification (coding.md#L135); otherwise code/artifacts are written in-place by cf-generate-coder-*, cf-generate-author-*, cf-pdsl-*, cf-migrate-migrator, etc. (all already isolation = false). Fix 1 simply moves the two phase agents onto that same in-place model.
Workaround
Run plan phases/compilation without worktree isolation (in the main checkout) — inline or via a non-isolated subagent — so all writes stay inside the working tree and no sandbox-escape prompts occur.
Note on regeneration
isolation: worktree is emitted by the agents generator, so any manual edit to the generated .claude/agents/*.md (or other tool targets) is overwritten on regenerate/update. The fix must change what the generator emits — i.e. the isolation value in skills/studio/agents.toml — not the generated files.
Affected tests (for whoever picks this up)
tests/test_subagent_registration.py
tests/test_agents_coverage.py
tests/test_agents_existing_snapshot.py
Summary
cf-phase-runnerandcf-phase-compilerare declared withisolation = true, which the generator translates toisolation: worktreefor Claude Code. But a plan's authoritative state lives under{cf-studio-path}/.plans/{task-slug}/(designed to be gitignored), and target SDLC artifacts are meant to be written in the main working tree. Worktree isolation is therefore structurally mismatched with plan execution/compilation: every meaningful write is a sandbox escape, and gitignored plan state is not even present inside the worktree.Root cause
Worktree isolation assumes the agent's working set lives inside the worktree. For phase execution/compilation that assumption is false:
{cf-studio-path}/.plans/{task-slug}/(workflows/plan.md#L76) and is intended to be gitignored on first use (architecture/features/execution-plans.md#L424; see also the notes at #L98 and #L472 — currently only.archive/is actually ignored).cf-phase-runnerreceivesplan_dirpointing at the main tree and must updateplan.tomland write artifacts there (cf-phase-runner.md#L30, #L104; dispatched at workflows/plan.md#L174).cf-phase-compilerwritesphase-NN-*.mdinto.plans/<slug>/(workflows/plan.md#L124).Both agents are
isolation = true:cf-phase-runner)cf-phase-compiler)The generator unconditionally emits
isolation: worktreewhenagent.isolationis true (agents.py#L1284, #L4588, #L5241).Net effect: writes to the canonical (main-tree) plan dir + SDLC outputs escape the worktree sandbox, triggering per-write permission prompts; gitignored plan state is absent from the worktree entirely.
Note that the generator is already configurable per agent —
isolationis a manifest field (defaultfalse, manifest.py#L82), and most write-capable agents (cf-generate-author-*,cf-generate-coder-*, the migrate-* set) are explicitlyisolation = falseand operate in-place. The phase agents are the remaining write-capable agents still set toisolation = true.Proposed fixes (pick one or combine)
isolation = falseforcf-phase-runnerandcf-phase-compilerinskills/studio/agents.tomlso they operate on the gitignored plan state in the main tree. Keep worktree only where parallel code mutation is the goal (cf-codegen). Update the agents' rationale comments (currently "write access is bounded by host isolation").{cf-studio-path}/.plans/<task-slug>/into the worktree, or stage plan artifacts under a non-gitignored, worktree-tracked location.validate,validate --artifact, list-ids, where-used/where-defined) and for writes under the plan dir + module docs.How fix 1 behaves
isolationis a per-dispatch property, not a session-wide mode: the orchestrator never runs in a worktree, and only a dispatched sub-agent whose frontmatter carriesisolation: worktreegets its own worktree for that one run. Sub-agents withisolation = falsewrite directly to the main tree.After fix 1, the only write-capable agent left in a worktree is
cf-codegen— which is the legitimate use (isolated code generation from a complete spec; it never touches plan state).cf-brainstorm-expertandcf-brainstorm-panelstayisolation = truebut are read-only, so the write-escape problem does not apply.This is also not "the only way code gets written":
cf-codegenis only the first-match path when a task is fully specified with no clarification (coding.md#L135); otherwise code/artifacts are written in-place bycf-generate-coder-*,cf-generate-author-*,cf-pdsl-*,cf-migrate-migrator, etc. (all alreadyisolation = false). Fix 1 simply moves the two phase agents onto that same in-place model.Workaround
Run plan phases/compilation without worktree isolation (in the main checkout) — inline or via a non-isolated subagent — so all writes stay inside the working tree and no sandbox-escape prompts occur.
Note on regeneration
isolation: worktreeis emitted by the agents generator, so any manual edit to the generated.claude/agents/*.md(or other tool targets) is overwritten on regenerate/update. The fix must change what the generator emits — i.e. theisolationvalue inskills/studio/agents.toml— not the generated files.Affected tests (for whoever picks this up)
tests/test_subagent_registration.pytests/test_agents_coverage.pytests/test_agents_existing_snapshot.py