feat(executor): add cross-AI execution hook (step 2.5) in execute-phase (#1875)
Add optional cross-AI delegation step that lets execute-phase delegate plans to external AI runtimes via stdin-based prompt delivery. Activated by --cross-ai flag, plan frontmatter cross_ai: true, or config key workflow.cross_ai_execution. Adds 3 config keys, template defaults, and 18 tests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -57,6 +57,8 @@ Parse `$ARGUMENTS` before loading any context:
|
||||
- First positional token → `PHASE_ARG`
|
||||
- Optional `--wave N` → `WAVE_FILTER`
|
||||
- Optional `--gaps-only` keeps its current meaning
|
||||
- Optional `--cross-ai` → `CROSS_AI_FORCE=true` (force all plans through cross-AI execution)
|
||||
- Optional `--no-cross-ai` → `CROSS_AI_DISABLED=true` (disable cross-AI for this run, overrides config and frontmatter)
|
||||
|
||||
If `--wave` is absent, preserve the current behavior of executing all incomplete waves in the phase.
|
||||
</step>
|
||||
@@ -243,6 +245,77 @@ Report:
|
||||
```
|
||||
</step>
|
||||
|
||||
<step name="cross_ai_delegation">
|
||||
**Optional step 2.5 — Delegate plans to an external AI runtime.**
|
||||
|
||||
This step runs after plan discovery and before normal wave execution. It identifies plans
|
||||
that should be delegated to an external AI command and executes them via stdin-based prompt
|
||||
delivery. Plans handled here are removed from the execute_waves plan list so the normal
|
||||
executor skips them.
|
||||
|
||||
**Activation logic:**
|
||||
|
||||
1. If `CROSS_AI_DISABLED` is true (`--no-cross-ai` flag): skip this step entirely.
|
||||
2. If `CROSS_AI_FORCE` is true (`--cross-ai` flag): mark ALL incomplete plans for cross-AI execution.
|
||||
3. Otherwise: check each plan's frontmatter for `cross_ai: true` AND verify config
|
||||
`workflow.cross_ai_execution` is `true`. Plans matching both conditions are marked for cross-AI.
|
||||
|
||||
```bash
|
||||
CROSS_AI_ENABLED=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.cross_ai_execution --default false 2>/dev/null)
|
||||
CROSS_AI_CMD=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.cross_ai_command --default "" 2>/dev/null)
|
||||
CROSS_AI_TIMEOUT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.cross_ai_timeout --default 300 2>/dev/null)
|
||||
```
|
||||
|
||||
**If no plans are marked for cross-AI:** Skip to execute_waves.
|
||||
|
||||
**If plans are marked but `cross_ai_command` is empty:** Error — tell user to set
|
||||
`workflow.cross_ai_command` via `gsd-tools.cjs config-set workflow.cross_ai_command "<command>"`.
|
||||
|
||||
**For each cross-AI plan (sequentially):**
|
||||
|
||||
1. **Construct the task prompt** from the plan file:
|
||||
- Extract `<objective>` and `<tasks>` sections from the PLAN.md
|
||||
- Append PROJECT.md context (project name, description, tech stack)
|
||||
- Format as a self-contained execution prompt
|
||||
|
||||
2. **Check for dirty working tree before execution:**
|
||||
```bash
|
||||
if ! git diff --quiet HEAD 2>/dev/null; then
|
||||
echo "WARNING: dirty working tree detected — the external AI command may produce uncommitted changes that conflict with existing modifications"
|
||||
fi
|
||||
```
|
||||
|
||||
3. **Run the external command** from the project root, writing the prompt to stdin.
|
||||
Never shell-interpolate the prompt — always pipe via stdin to prevent injection:
|
||||
```bash
|
||||
echo "$TASK_PROMPT" | timeout "${CROSS_AI_TIMEOUT}s" ${CROSS_AI_CMD} > "$CANDIDATE_SUMMARY" 2>"$ERROR_LOG"
|
||||
EXIT_CODE=$?
|
||||
```
|
||||
|
||||
4. **Evaluate the result:**
|
||||
|
||||
**Success (exit 0 + valid summary):**
|
||||
- Read `$CANDIDATE_SUMMARY` and validate it contains meaningful content
|
||||
(not empty, has at least a heading and description — a valid SUMMARY.md structure)
|
||||
- Write it as the plan's SUMMARY.md file
|
||||
- Update STATE.md plan status to complete
|
||||
- Update ROADMAP.md progress
|
||||
- Mark plan as handled — skip it in execute_waves
|
||||
|
||||
**Failure (non-zero exit or invalid summary):**
|
||||
- Display the error output and exit code
|
||||
- Warn: "The external command may have left uncommitted changes or partial edits
|
||||
in the working tree. Review `git status` and `git diff` before proceeding."
|
||||
- Offer three choices:
|
||||
- **retry** — run the same plan through cross-AI again
|
||||
- **skip** — fall back to normal executor for this plan (re-add to execute_waves list)
|
||||
- **abort** — stop execution entirely, preserve state for resume
|
||||
|
||||
5. **After all cross-AI plans processed:** Remove successfully handled plans from the
|
||||
incomplete plan list so execute_waves skips them. Any skipped-to-fallback plans remain
|
||||
in the list for normal executor processing.
|
||||
</step>
|
||||
|
||||
<step name="execute_waves">
|
||||
Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZATION=true`, sequential if `false`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user