fix(#913): guard top-level Claude Code plan-phase against role collapse (#915)

Three-part fix for the top-level inline collapse bug:

1. plan-phase.md: add <runtime_compatibility> block after
   </available_agent_types> that makes the Agent-availability
   requirement explicit; workflow fails-closed (stops with a clear
   log) in genuinely Agent-less contexts.

2. plan-phase.md: rename 7 "ORCHESTRATOR RULE — CODEX RUNTIME"
   labels to "ALL RUNTIMES" so the spawn guard applies universally
   (not just when Codex is detected).

3. execute-phase.md: scope the existing "Other runtimes" inline-
   fallback prose to non-Claude contexts, preserving the #853
   backgrounded-agent behaviour for Claude Code background agents.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 5bf77a527f)
This commit is contained in:
Tom Boucher
2026-06-08 23:32:34 -04:00
committed by github-actions[bot]
parent e0f67c75cd
commit bb27263def
5 changed files with 104 additions and 13 deletions

View File

@@ -14,8 +14,11 @@ Orchestrator coordinates, not executes. Each subagent loads the full execute-pla
instead of spawning parallel agents. Only attempt parallel spawning if the user
explicitly requests it — and in that case, rely on the spot-check fallback in step 3
to detect completion.
- **Other runtimes:** If `Agent`/`agent` tool is unavailable, use sequential inline execution as the
fallback. Check for tool availability at runtime rather than assuming based on runtime name.
- **Other runtimes:** If `Agent`/`agent` tool is genuinely unavailable (e.g. a backgrounded
Claude Code agent per #853, or a non-Claude runtime), use sequential inline execution as
the fallback for executor parallelization only. If `Agent` IS available (top-level Claude
Code), you MUST spawn gsd-executor agents — inline execution is not authorized. Check for
actual tool availability, not runtime name.
**Fallback rule:** If a spawned agent completes its work (commits visible, SUMMARY.md exists) but
the orchestrator never receives the completion signal, treat it as successful based on spot-checks

View File

@@ -20,6 +20,31 @@ Valid GSD subagent types (use exact names — do not fall back to 'general-purpo
- gsd-plan-checker — Reviews plan quality before execution
</available_agent_types>
<runtime_compatibility>
**Subagent spawning — top-level Claude Code:**
The Agent tool IS available in a top-level Claude Code session. Always spawn
gsd-phase-researcher, gsd-planner, and gsd-plan-checker as separate Agent() calls.
Never absorb these roles inline. Role separation is required regardless of `--chain`
or `--auto` — those options suppress interactive prompts only; they NEVER authorize
collapsing plan roles into the orchestrator context.
**Backgrounded Claude Code (via manager/autonomous):**
The calling workflow (manager.md / autonomous.md) already runs plan-phase inline via
Skill() on Claude Code so that the plan-checker subagent can still spawn. plan-phase
itself does not need to detect this case.
**#1009 caveat (discuss-phase early-exit):**
The "display the command and exit" instruction near `## 4` applies only to the
discuss-phase early-exit path. It does NOT authorize inline role performance for any
plan-phase agents.
**Other runtimes:**
If the Agent tool is genuinely absent (e.g. a backgrounded Claude Code agent per
#853, or a non-Claude runtime that does not expose Agent/agent), log the gap and
stop — do NOT perform researcher/planner/checker roles inline. Independent agent
contexts are required for the plan-checker gate to be meaningful.
</runtime_compatibility>
<process>
## 0. Git Branch Invariant
@@ -530,7 +555,7 @@ Agent(
)
```
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
> **ORCHESTRATOR RULE — ALL RUNTIMES**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
### Handle Researcher Return
@@ -849,7 +874,7 @@ Agent(
)
```
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
> **ORCHESTRATOR RULE — ALL RUNTIMES**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
**Handle return:**
- **`## PATTERN MAPPING COMPLETE`:** Update `PATTERNS_PATH` to the created file path, continue to step 8.
@@ -1012,7 +1037,7 @@ Agent(
)
```
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
> **ORCHESTRATOR RULE — ALL RUNTIMES**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
**If `CHUNKED_MODE` is `true`:** Skip the Agent() call above — proceed to step 8.5 instead.
@@ -1068,7 +1093,7 @@ Agent(
)
```
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
> **ORCHESTRATOR RULE — ALL RUNTIMES**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
Handle return:
- **`## OUTLINE COMPLETE`:** Read `PLAN-OUTLINE.md`, extract plan list. Continue to 8.5.2.
@@ -1112,7 +1137,7 @@ For each plan entry extracted from `PLAN-OUTLINE.md`:
)
```
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
> **ORCHESTRATOR RULE — ALL RUNTIMES**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
4. **Verify disk:** Check `${PHASE_DIR}/{plan_id}-PLAN.md` exists. If missing: offer 1) Retry, 2) Stop.
@@ -1270,7 +1295,7 @@ Agent(
)
```
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
> **ORCHESTRATOR RULE — ALL RUNTIMES**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
## 11. Handle Checker Return
@@ -1385,7 +1410,7 @@ Agent(
)
```
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
> **ORCHESTRATOR RULE — ALL RUNTIMES**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
After planner returns -> spawn checker again (step 10), increment iteration_count.