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:
committed by
github-actions[bot]
parent
e0f67c75cd
commit
bb27263def
@@ -135,3 +135,61 @@ describe('plan-phase workflow: Artifacts this phase produces section (#22)', ()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── (C) Top-level spawn guard (#913) ────────────────────────────────────────
|
||||
|
||||
describe('plan-phase workflow: top-level spawn guard (#913)', () => {
|
||||
// Extract the runtime_compatibility block for targeted assertions
|
||||
const rtBlock = (() => {
|
||||
const m = workflow.match(/<runtime_compatibility>([\s\S]*?)<\/runtime_compatibility>/);
|
||||
return m ? m[1] : '';
|
||||
})();
|
||||
|
||||
test('workflow has a runtime_compatibility block asserting Agent is available at top-level', () => {
|
||||
assert.ok(
|
||||
rtBlock.length > 0,
|
||||
'plan-phase must have a <runtime_compatibility> block — prevents role-collapse regression (#913)'
|
||||
);
|
||||
assert.ok(
|
||||
rtBlock.includes('Agent tool IS available') || rtBlock.includes('Agent IS available'),
|
||||
'plan-phase runtime_compatibility must assert that the Agent tool IS available at top-level Claude Code (#913)'
|
||||
);
|
||||
assert.ok(
|
||||
rtBlock.toLowerCase().includes('top-level'),
|
||||
'plan-phase runtime_compatibility must scope the IS-available assertion to top-level Claude Code (#913)'
|
||||
);
|
||||
assert.ok(
|
||||
rtBlock.includes('Always spawn') || rtBlock.includes('always spawn'),
|
||||
'plan-phase runtime_compatibility must state that plan roles must always be spawned (#913)'
|
||||
);
|
||||
assert.ok(
|
||||
rtBlock.includes('Never absorb') || rtBlock.includes('never absorb'),
|
||||
'plan-phase runtime_compatibility must state that roles must never be absorbed inline (#913)'
|
||||
);
|
||||
});
|
||||
|
||||
test('workflow states --chain/--auto suppress prompts only, not spawns', () => {
|
||||
assert.ok(
|
||||
rtBlock.includes('suppress') &&
|
||||
(rtBlock.includes('prompts only') || rtBlock.includes('interactive prompts only')),
|
||||
'plan-phase runtime_compatibility must document that --chain/--auto suppress prompts only, not spawns (#913)'
|
||||
);
|
||||
});
|
||||
|
||||
test('workflow does not contain unscoped CODEX RUNTIME orchestrator rule labels', () => {
|
||||
// All "wait for subagent" rules must apply to ALL RUNTIMES, not just Codex
|
||||
assert.ok(
|
||||
!workflow.includes('ORCHESTRATOR RULE — CODEX RUNTIME'),
|
||||
'plan-phase must not label orchestrator wait rules as "CODEX RUNTIME" — they apply to all runtimes including top-level Claude Code (#913)'
|
||||
);
|
||||
});
|
||||
|
||||
test('workflow contains ALL RUNTIMES orchestrator rule labels (count preserved)', () => {
|
||||
// Must have all 7 agent-spawn wait rules still present (none dropped during rename)
|
||||
const allRuntimesCount = (workflow.match(/ORCHESTRATOR RULE — ALL RUNTIMES/g) || []).length;
|
||||
assert.ok(
|
||||
allRuntimesCount >= 7,
|
||||
`plan-phase must have at least 7 "ORCHESTRATOR RULE — ALL RUNTIMES" labels (one per agent spawn site); found ${allRuntimesCount} (#913)`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -81,8 +81,8 @@ const GRACE = 3000;
|
||||
// current high-water mark within GRACE (#597 tighten-only ratchet).
|
||||
// XL high-water mark is execute-phase.md — note that under LINES it was
|
||||
// plan-phase; bytes genuinely re-rank the tier, which is the point of #717.
|
||||
// actualMax=91161 (execute-phase, #891 launcher shim expansion — added 17 runtime home arms);
|
||||
// slack=1839 ≤ GRACE. plan-phase.md=88120, new-project.md=58110; both well under ceiling.
|
||||
// actualMax=92525 (execute-phase, #913 inline-fallback scope clarification);
|
||||
// slack=475 ≤ GRACE. plan-phase.md=90501 (#913 runtime_compatibility block + label rename), new-project.md=58110.
|
||||
const XL_BUDGET = 93000;
|
||||
// LARGE high-water mark is docs-update.md. actualMax=54410 (#891 launcher shim expansion);
|
||||
// slack=1590 ≤ GRACE. quick.md=45710, autonomous.md=38030.
|
||||
@@ -95,8 +95,8 @@ const DEFAULT_BUDGET = 40000;
|
||||
// Grandfathered at current sizes — see PR #2551 for the progressive-disclosure
|
||||
// pattern that future shrinks should follow. Byte counts noted for reference.
|
||||
const XL_WORKFLOWS = new Set([
|
||||
'execute-phase', // 91161 bytes (tier high-water mark; grew in #891 launcher shim expansion)
|
||||
'plan-phase', // 85068 bytes
|
||||
'execute-phase', // 92525 bytes (tier high-water mark; grew in #913 inline-fallback scope clarification)
|
||||
'plan-phase', // 90501 bytes (grew in #913 runtime_compatibility block + label rename)
|
||||
'new-project', // 55850 bytes
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user