feat(codex): carve the three mutually exclusive modes into sections

Review/Challenge/Consult mode bodies (34.7KB where at most one ever runs)
load on demand: skeleton 81.0KB -> 55.2KB, union 1.04x the monolith. The mode
dispatch, filesystem boundary, and a new always-loaded 'Synthesis
recommendation (REQUIRED) — all modes' block stay skeleton-side (the AUQ
per-skill pins pass unchanged); the plan-file report + exit gate render after
the last section pointer per the gateAfterStop pattern.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-08-25 16:36:02 +00:00
co-authored by Claude Fable 5
parent 3a78bf7c1d
commit 87589961a4
13 changed files with 1184 additions and 1044 deletions
+11
View File
@@ -56,6 +56,17 @@ describe('deprecated codex web-search flag is gone (#2525)', () => {
expect(rendered).not.toContain('{{CODEX_WEB_SEARCH_FLAG}}');
});
test('rendered codex mode sections resolve the token at every invocation site', () => {
// The mode bodies (and their codex invocations) are carved into
// codex/sections/*-mode.md (T9) — each generated section must carry the
// live flag, never the unresolved token.
for (const file of ['review-mode.md', 'challenge-mode.md', 'consult-mode.md']) {
const rendered = fs.readFileSync(path.join(ROOT, 'codex', 'sections', file), 'utf-8');
expect(rendered, `${file} lost the web-search flag`).toContain(CODEX_WEB_SEARCH_FLAG);
expect(rendered).not.toContain('{{CODEX_WEB_SEARCH_FLAG}}');
}
});
test('rendered autoplan skill resolves the token at every inline site', () => {
const rendered = fs.readFileSync(path.join(ROOT, 'autoplan', 'SKILL.md'), 'utf-8');
const count = rendered.split(CODEX_WEB_SEARCH_FLAG).length - 1;
+4 -2
View File
@@ -92,10 +92,12 @@ describe('#2091/#2370 bug 1: every mktemp template is BSD-safe (X placeholder at
test('scan sweep finds the known mktemp call sites (not vacuous)', () => {
// Guards against the walker silently matching nothing after a refactor.
// codex's mktemp calls live in the carved mode sections (T9), not the
// skeleton — the walker scans their .tmpl sources.
const withMktemp = files.filter((f) => fs.readFileSync(f, 'utf-8').includes('mktemp'));
expect(withMktemp.length).toBeGreaterThanOrEqual(5);
expect(withMktemp).toContain(path.join(ROOT, 'codex', 'SKILL.md.tmpl'));
expect(withMktemp).toContain(path.join(ROOT, 'codex', 'SKILL.md'));
expect(withMktemp).toContain(path.join(ROOT, 'codex', 'sections', 'review-mode.md.tmpl'));
expect(withMktemp).toContain(path.join(ROOT, 'codex', 'sections', 'consult-mode.md.tmpl'));
expect(withMktemp).toContain(path.join(ROOT, 'scripts', 'resolvers', 'review.ts'));
});
@@ -22,28 +22,31 @@ import * as path from 'path';
const ROOT = path.resolve(import.meta.dir, '..');
describe('cross-model synthesis emit instructions', () => {
test('codex/SKILL.md.tmpl Step 2A (review) requires a synthesis Recommendation', () => {
const tmpl = fs.readFileSync(path.join(ROOT, 'codex', 'SKILL.md.tmpl'), 'utf-8');
const step2a = sliceBetween(tmpl, '## Step 2A:', '## Step 2B:');
expect(step2a, 'Step 2A section not found in codex template').not.toBe('');
expect(step2a).toMatch(/Synthesis recommendation \(REQUIRED\)/);
expect(step2a).toMatch(/Recommendation:\s*<action>\s*because/);
});
// The three codex modes are carved into codex/sections/*-mode.md.tmpl (T9);
// each mode section must still carry its own emit instruction so the rule is
// in context when that (mutually exclusive) mode's section is loaded.
const CODEX_MODE_SECTIONS: Array<[string, string]> = [
['review-mode.md.tmpl', '## Step 2A:'],
['challenge-mode.md.tmpl', '## Step 2B:'],
['consult-mode.md.tmpl', '## Step 2C:'],
];
test('codex/SKILL.md.tmpl Step 2B (challenge) requires a synthesis Recommendation', () => {
const tmpl = fs.readFileSync(path.join(ROOT, 'codex', 'SKILL.md.tmpl'), 'utf-8');
const step2b = sliceBetween(tmpl, '## Step 2B:', '## Step 2C:');
expect(step2b, 'Step 2B section not found in codex template').not.toBe('');
expect(step2b).toMatch(/Synthesis recommendation \(REQUIRED\)/);
expect(step2b).toMatch(/Recommendation:\s*<action>\s*because/);
});
for (const [file, heading] of CODEX_MODE_SECTIONS) {
test(`codex/sections/${file} requires a synthesis Recommendation`, () => {
const tmpl = fs.readFileSync(path.join(ROOT, 'codex', 'sections', file), 'utf-8');
expect(tmpl, `${file} lost its ${heading} heading`).toContain(heading);
expect(tmpl).toMatch(/Synthesis recommendation \(REQUIRED\)/);
expect(tmpl).toMatch(/Recommendation:\s*<action>\s*because/);
});
}
test('codex/SKILL.md.tmpl Step 2C (consult) requires a synthesis Recommendation', () => {
test('codex/SKILL.md.tmpl skeleton keeps the always-loaded synthesis rule', () => {
// The AUQ safety net (test/auq-format-always-loaded.test.ts) requires the
// canonical rule in the ALWAYS-LOADED skeleton, not only in the on-demand
// mode sections — a question can fire before any section is read.
const tmpl = fs.readFileSync(path.join(ROOT, 'codex', 'SKILL.md.tmpl'), 'utf-8');
const step2c = sliceBetween(tmpl, '## Step 2C:', '## Model & Reasoning');
expect(step2c, 'Step 2C section not found in codex template').not.toBe('');
expect(step2c).toMatch(/Synthesis recommendation \(REQUIRED\)/);
expect(step2c).toMatch(/Recommendation:\s*<action>\s*because/);
expect(tmpl).toMatch(/Synthesis recommendation \(REQUIRED\)/);
expect(tmpl).toMatch(/Recommendation:\s*<action>\s*because/);
});
test('scripts/resolvers/review.ts Claude adversarial subagent prompt requires Recommendation', () => {
+23 -9
View File
@@ -473,17 +473,31 @@ describeIfSelected('Codex skill E2E', ['codex-review'], () => {
run('git', ['add', 'user_controller.rb']);
run('git', ['commit', '-m', 'add vulnerable controller']);
// Extract only the review-relevant section from codex SKILL.md (~120 lines vs 1075).
// Full SKILL.md is 55KB / ~14K tokens — takes 8 Read calls to consume, exhausting turns.
// Extract only the review-relevant content (CLAUDE.md: "extract, don't copy").
// The codex skill is carved (T9): the skeleton carries setup + dispatch and
// STOP-points to codex/sections/*-mode.md. Build the fixture from the
// skeleton's setup slices plus the review-mode section body, SKIPPING the
// Section index and STOP pointers — their install paths don't exist in this
// temp fixture dir and would burn agent turns on failed Reads.
const full = fs.readFileSync(path.join(ROOT, 'codex', 'SKILL.md'), 'utf-8');
const startMarker = '# /codex — Multi-AI Second Opinion';
const endMarker = '## Plan File Review Report';
const start = full.indexOf(startMarker);
const end = full.indexOf(endMarker, start);
const reviewSection = full.slice(
start >= 0 ? start : 0,
end > start ? end : undefined,
const introStart = full.indexOf('# /codex — Multi-AI Second Opinion');
const introEnd = full.indexOf('## Section index', introStart);
const stepsStart = full.indexOf('## Step 0.4', introStart);
const stepsEnd = full.indexOf('> **STOP.**', stepsStart);
expect(introStart).toBeGreaterThan(-1);
expect(introEnd).toBeGreaterThan(introStart);
expect(stepsStart).toBeGreaterThan(introEnd);
expect(stepsEnd).toBeGreaterThan(stepsStart);
const reviewMode = fs.readFileSync(
path.join(ROOT, 'codex', 'sections', 'review-mode.md'),
'utf-8',
);
expect(reviewMode).toContain('## Step 2A: Review Mode'); // non-empty, right section
const reviewSection = [
full.slice(introStart, introEnd),
full.slice(stepsStart, stepsEnd),
reviewMode,
].join('\n');
fs.writeFileSync(path.join(codexDir, 'codex-SKILL.md'), reviewSection);
});