fix(review,autoplan): require explicit run_in_background: false on specialist agents

Claude Code v2.1.198 made subagents run in the background by default, which
inverted the old "do not use the flag" guidance: review-army specialists and
autoplan dual voices silently launched in the background and the merge step
could proceed before they completed — regressing the #497 fix. The generated
guidance now instructs an explicit run_in_background: false, and a static
tripwire fails the free suite if the inert inverted phrasing ever returns to
any generated SKILL.md.

Fixes #2440.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-08-14 20:20:48 -07:00
co-authored by Claude Fable 5
parent 5084f85e00
commit e684948efe
7 changed files with 78 additions and 10 deletions
+4 -3
View File
@@ -1154,9 +1154,10 @@ Override: every AskUserQuestion → auto-decide using the 6 principles.
Duplicates → reject (P4). Borderline (3-5 files) → mark TASTE DECISION. Duplicates → reject (P4). Borderline (3-5 files) → mark TASTE DECISION.
- All 10 review sections: run fully, auto-decide each issue, log every decision. - All 10 review sections: run fully, auto-decide each issue, log every decision.
- Dual voices: always run BOTH Claude subagent AND Codex if available (P6). - Dual voices: always run BOTH Claude subagent AND Codex if available (P6).
Run them sequentially in foreground. First the Claude subagent (Agent tool, Run them sequentially in foreground. First the Claude subagent (Agent tool
foreground — do NOT use run_in_background), then Codex (Bash). Both must with run_in_background: false — subagents default to BACKGROUND since
complete before building the consensus table. Claude Code v2.1.198, so the flag must be explicitly false), then Codex
(Bash). Both must complete before building the consensus table.
**Codex CEO voice** (via Bash): **Codex CEO voice** (via Bash):
```bash ```bash
+4 -3
View File
@@ -290,9 +290,10 @@ Override: every AskUserQuestion → auto-decide using the 6 principles.
Duplicates → reject (P4). Borderline (3-5 files) → mark TASTE DECISION. Duplicates → reject (P4). Borderline (3-5 files) → mark TASTE DECISION.
- All 10 review sections: run fully, auto-decide each issue, log every decision. - All 10 review sections: run fully, auto-decide each issue, log every decision.
- Dual voices: always run BOTH Claude subagent AND Codex if available (P6). - Dual voices: always run BOTH Claude subagent AND Codex if available (P6).
Run them sequentially in foreground. First the Claude subagent (Agent tool, Run them sequentially in foreground. First the Claude subagent (Agent tool
foreground — do NOT use run_in_background), then Codex (Bash). Both must with run_in_background: false — subagents default to BACKGROUND since
complete before building the consensus table. Claude Code v2.1.198, so the flag must be explicitly false), then Codex
(Bash). Both must complete before building the consensus table.
**Codex CEO voice** (via Bash): **Codex CEO voice** (via Bash):
```bash ```bash
+1 -1
View File
@@ -1395,7 +1395,7 @@ CHECKLIST:
**Subagent configuration:** **Subagent configuration:**
- Use `subagent_type: "general-purpose"` - Use `subagent_type: "general-purpose"`
- Do NOT use `run_in_background` — all specialists must complete before merge - Pass `run_in_background: false` on every specialist Agent call — subagents run in the BACKGROUND by default since Claude Code v2.1.198, and all specialists must complete before merge. (Merely omitting the flag no longer produces a foreground run; it must be explicitly false.)
- If any specialist subagent fails or times out, log the failure and continue with results from successful specialists. Specialists are additive — partial results are better than no results. - If any specialist subagent fails or times out, log the failure and continue with results from successful specialists. Specialists are additive — partial results are better than no results.
--- ---
+1 -1
View File
@@ -129,7 +129,7 @@ CHECKLIST:
**Subagent configuration:** **Subagent configuration:**
- Use \`subagent_type: "general-purpose"\` - Use \`subagent_type: "general-purpose"\`
- Do NOT use \`run_in_background\` — all specialists must complete before merge - Pass \`run_in_background: false\` on every specialist Agent call — subagents run in the BACKGROUND by default since Claude Code v2.1.198, and all specialists must complete before merge. (Merely omitting the flag no longer produces a foreground run; it must be explicitly false.)
- If any specialist subagent fails or times out, log the failure and continue with results from successful specialists. Specialists are additive partial results are better than no results.`; - If any specialist subagent fails or times out, log the failure and continue with results from successful specialists. Specialists are additive partial results are better than no results.`;
} }
+1 -1
View File
@@ -245,7 +245,7 @@ CHECKLIST:
**Subagent configuration:** **Subagent configuration:**
- Use `subagent_type: "general-purpose"` - Use `subagent_type: "general-purpose"`
- Do NOT use `run_in_background` — all specialists must complete before merge - Pass `run_in_background: false` on every specialist Agent call — subagents run in the BACKGROUND by default since Claude Code v2.1.198, and all specialists must complete before merge. (Merely omitting the flag no longer produces a foreground run; it must be explicitly false.)
- If any specialist subagent fails or times out, log the failure and continue with results from successful specialists. Specialists are additive — partial results are better than no results. - If any specialist subagent fails or times out, log the failure and continue with results from successful specialists. Specialists are additive — partial results are better than no results.
--- ---
+1 -1
View File
@@ -2177,7 +2177,7 @@ CHECKLIST:
**Subagent configuration:** **Subagent configuration:**
- Use `subagent_type: "general-purpose"` - Use `subagent_type: "general-purpose"`
- Do NOT use `run_in_background` — all specialists must complete before merge - Pass `run_in_background: false` on every specialist Agent call — subagents run in the BACKGROUND by default since Claude Code v2.1.198, and all specialists must complete before merge. (Merely omitting the flag no longer produces a foreground run; it must be explicitly false.)
- If any specialist subagent fails or times out, log the failure and continue with results from successful specialists. Specialists are additive — partial results are better than no results. - If any specialist subagent fails or times out, log the failure and continue with results from successful specialists. Specialists are additive — partial results are better than no results.
--- ---
+66
View File
@@ -0,0 +1,66 @@
import { describe, test, expect } from 'bun:test';
import * as fs from 'fs';
import * as path from 'path';
// Regression guard for #2440 (which itself regressed the #497 fix).
//
// Claude Code v2.1.198 made subagents run in the BACKGROUND by default.
// Guidance written before that ("do NOT use run_in_background") stopped
// producing a foreground run — the review army and autoplan dual-voice
// steps silently launched specialists in the background and merged before
// they completed. The only guidance that works post-2.1.198 is an explicit
// `run_in_background: false` on the Agent call.
//
// This tripwire pins the corrected phrasing in the generated skill output
// and fails if the inverted form ever comes back through a template or
// resolver edit.
const ROOT = path.resolve(import.meta.dir, '..');
const GENERATED_WITH_GUIDANCE = ['review/SKILL.md', 'autoplan/SKILL.md'];
// The inverted, post-2.1.198-inert phrasings. Checked across every generated
// SKILL.md so the regression can't migrate to another skill unnoticed.
const INVERTED = /do not use\s+`?run_in_background`?/i;
function allGeneratedSkillFiles(): string[] {
const out: string[] = [];
for (const entry of fs.readdirSync(ROOT, { withFileTypes: true })) {
if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === 'node_modules') continue;
const p = path.join(ROOT, entry.name, 'SKILL.md');
if (fs.existsSync(p)) out.push(p);
// Generated on-demand section files (e.g. ship/sections/review-army.md)
// carry the same resolver output as SKILL.md bodies — scan them too.
const sections = path.join(ROOT, entry.name, 'sections');
if (fs.existsSync(sections)) {
for (const f of fs.readdirSync(sections)) {
if (f.endsWith('.md')) out.push(path.join(sections, f));
}
}
}
const rootSkill = path.join(ROOT, 'SKILL.md');
if (fs.existsSync(rootSkill)) out.push(rootSkill);
return out;
}
describe('run_in_background guidance (#2440)', () => {
test('foreground-required skills instruct run_in_background: false explicitly', () => {
for (const rel of GENERATED_WITH_GUIDANCE) {
const content = fs.readFileSync(path.join(ROOT, rel), 'utf-8');
expect(content).toContain('run_in_background: false');
}
});
test('the inverted "do NOT use run_in_background" phrasing never comes back', () => {
for (const file of allGeneratedSkillFiles()) {
const content = fs.readFileSync(file, 'utf-8');
if (INVERTED.test(content)) {
throw new Error(
`${path.relative(ROOT, file)} contains the inverted run_in_background guidance — ` +
'since Claude Code v2.1.198 subagents default to background, so "do not use" is inert; ' +
'instruct `run_in_background: false` instead (see #2440).',
);
}
}
});
});