Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions model-overlays/opus-4-8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{{INHERIT:claude}}

**Effort-match the step.** Simple file reads, config checks, command lookups, and
mechanical edits don't need deep reasoning. Complete them quickly and move on. Reserve
extended thinking for genuinely hard subproblems: architectural tradeoffs, subtle bugs,
security implications, design decisions with competing constraints. Over-thinking
simple steps wastes tokens and time.

**Pace questions to the skill.** If the current skill's text contains
`STOP. AskUserQuestion` anywhere, pace one question per turn — emit the question as
a tool_use, stop, wait for the user's response, then continue. Do not batch. A
finding with an "obvious fix" is still a finding and still needs user approval
before it lands in the plan. Only batch clarifying questions upfront when (a) the
skill has no `STOP. AskUserQuestion` directive AND (b) you need multiple unrelated
clarifications before you can begin. When in doubt, ask one question per turn.

**Literal interpretation awareness.** Opus 4.8 interprets instructions literally and
will not silently generalize. When the user says "fix the tests," fix all failing tests
that this branch introduced or is responsible for, not just the first one (and not
pre-existing failures in unrelated code). When the user says "update the docs," update
every relevant doc in scope, not just the most obvious one. Read the full scope of what
was asked and deliver the full scope. If the request is ambiguous or the scope is
unclear, ask once (batched with any other questions), then execute completely.
2 changes: 2 additions & 0 deletions scripts/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
export const ALL_MODEL_NAMES = [
'claude',
'opus-4-7',
'opus-4-8',
'gpt',
'gpt-5.4',
'gemini',
Expand Down Expand Up @@ -53,6 +54,7 @@ export function resolveModel(input: string): Model | null {
if (/^gpt(-|$)/.test(s)) return 'gpt';
if (/^o[0-9]+(-|$)/.test(s)) return 'o-series';
if (/^claude-opus-4-7(-|$)/.test(s)) return 'opus-4-7';
if (/^claude-opus-4-8(-|$)/.test(s)) return 'opus-4-8';
if (/^claude(-|$)/.test(s)) return 'claude';
if (/^gemini(-|$)/.test(s)) return 'gemini';

Expand Down
92 changes: 92 additions & 0 deletions test/model-overlay-opus-4-8.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* Opus 4.8 model overlay — gate-tier assertions on the pacing directive.
*
* opus-4-8 mirrors opus-4-7's Opus-4.x family nudges: it inherits the claude
* base and adds effort-matching, skill-paced questions (one-per-turn when the
* skill carries STOP directives), and complete-scope literal execution.
*
* This test asserts:
* - The "Pace questions to the skill" directive is present
* - The old "Batch your questions" directive is absent
* - The AUTO_DECIDE-compatible language survives (subordination, skill wins)
* - The claude base is inherited (INHERIT:claude)
*/
import { describe, test, expect } from 'bun:test';
import * as fs from 'fs';
import * as path from 'path';
import type { TemplateContext } from '../scripts/resolvers/types';
import { HOST_PATHS } from '../scripts/resolvers/types';
import { generateModelOverlay } from '../scripts/resolvers/model-overlay';

function makeCtx(model: string): TemplateContext {
return {
skillName: 'test-skill',
tmplPath: 'test.tmpl',
host: 'claude',
paths: HOST_PATHS.claude,
preambleTier: 2,
model,
};
}

const ROOT = path.resolve(__dirname, '..');

describe('Opus 4.8 overlay — pacing directive', () => {
test('raw opus-4-8.md contains "Pace questions to the skill"', () => {
const raw = fs.readFileSync(
path.join(ROOT, 'model-overlays/opus-4-8.md'),
'utf-8',
);
expect(raw).toContain('Pace questions to the skill');
});

test('raw opus-4-8.md does NOT contain "Batch your questions" directive', () => {
const raw = fs.readFileSync(
path.join(ROOT, 'model-overlays/opus-4-8.md'),
'utf-8',
);
expect(raw).not.toContain('**Batch your questions.**');
});

test('resolved overlay output contains "Pace questions to the skill"', () => {
const out = generateModelOverlay(makeCtx('opus-4-8'));
expect(out).toContain('Pace questions to the skill');
});

test('resolved overlay inherits from claude base (INHERIT:claude)', () => {
const out = generateModelOverlay(makeCtx('opus-4-8'));
// The claude base contributes the subordination wrapper + Todo discipline
expect(out).toContain('Todo-list discipline');
expect(out).toContain('subordinate');
});

test('resolved overlay says skill STOP directives trigger one-per-turn pacing', () => {
const out = generateModelOverlay(makeCtx('opus-4-8'));
expect(out).toMatch(/STOP\. AskUserQuestion/);
expect(out).toMatch(/pace one question per turn|one question per turn/i);
});

test('resolved overlay requires AskUserQuestion as tool_use', () => {
const out = generateModelOverlay(makeCtx('opus-4-8'));
expect(out).toContain('tool_use');
});

test('resolved overlay flags "obvious fix" findings still need user approval', () => {
const out = generateModelOverlay(makeCtx('opus-4-8'));
expect(out).toMatch(/obvious fix/i);
expect(out).toMatch(/user approval/i);
});

test('resolved overlay keeps Effort-match / Literal interpretation nudges', () => {
const out = generateModelOverlay(makeCtx('opus-4-8'));
expect(out).toContain('Effort-match the step');
expect(out).toContain('Literal interpretation awareness');
});

test('claude overlay (no INHERIT chain) does not carry the pacing directive', () => {
// Claude is the default overlay; opus-4-8 inherits FROM claude.
// The pacing directive belongs to the opus-4-x overlays only.
const out = generateModelOverlay(makeCtx('claude'));
expect(out).not.toContain('Pace questions to the skill');
});
});