mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-13 08:29:04 +02:00
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:
co-authored by
Claude Fable 5
parent
3a78bf7c1d
commit
87589961a4
@@ -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;
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user