From 2f19b03b9b1df3351010883d7f2627721d251863 Mon Sep 17 00:00:00 2001 From: ChrisQuorum Date: Sun, 12 Jul 2026 11:20:09 -0400 Subject: [PATCH] feat(model-overlays): add fable-5 overlay + resolver mapping Give claude-fable-5 a dedicated overlay instead of the generic claude fallback: inherits the claude base plus Fable-family nudges (act when ready, ground progress claims, assessment-vs-action, delegate). Adds the models.ts resolver mapping and a gate-tier test mirroring the opus overlays. --- model-overlays/fable-5.md | 23 +++++++++++++ scripts/models.ts | 2 ++ test/model-overlay-fable-5.test.ts | 55 ++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 model-overlays/fable-5.md create mode 100644 test/model-overlay-fable-5.test.ts diff --git a/model-overlays/fable-5.md b/model-overlays/fable-5.md new file mode 100644 index 0000000000..3e1a15ceb8 --- /dev/null +++ b/model-overlays/fable-5.md @@ -0,0 +1,23 @@ +{{INHERIT:claude}} + +**Act when you have enough to act.** Fable 5 can over-plan on ambiguous tasks. +When you have enough information to act, act. Do not re-derive facts already +established in the conversation, re-litigate a decision the user has already made, +or narrate options you will not pursue in user-facing messages. Give a +recommendation, not an exhaustive survey. This does not apply to thinking blocks. + +**Ground progress claims in evidence.** Before reporting progress, audit each +claim against a tool result from this session. Report only work you can point to; +if something is not yet verified, say so. If tests fail, say so with the output; +if a step was skipped, say that; when something is done and verified, state it +plainly without hedging. + +**Assessment vs action.** When the user is describing a problem, asking a +question, or thinking out loud rather than requesting a change, the deliverable is +your assessment: report findings and stop. Don't apply a fix until they ask. Before +a state-changing command (restart, delete, config edit), confirm the evidence +supports that specific action. + +**Delegate independent work.** When a task fans out across independent items, +delegate to sub-agents and keep working while they run, rather than iterating +serially. Intervene if a sub-agent goes off track or is missing context. diff --git a/scripts/models.ts b/scripts/models.ts index b6d1d368d5..62177295dc 100644 --- a/scripts/models.ts +++ b/scripts/models.ts @@ -14,6 +14,7 @@ export const ALL_MODEL_NAMES = [ 'claude', 'opus-4-7', + 'fable-5', 'gpt', 'gpt-5.4', 'gemini', @@ -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-fable-5(-|$)/.test(s)) return 'fable-5'; if (/^claude(-|$)/.test(s)) return 'claude'; if (/^gemini(-|$)/.test(s)) return 'gemini'; diff --git a/test/model-overlay-fable-5.test.ts b/test/model-overlay-fable-5.test.ts new file mode 100644 index 0000000000..537a4c03ad --- /dev/null +++ b/test/model-overlay-fable-5.test.ts @@ -0,0 +1,55 @@ +/** + * Fable 5 model overlay — gate-tier assertions on the family nudges. + * + * fable-5 inherits the claude base and adds Fable-family nudges: act when you + * have enough context (avoid over-planning), ground progress claims in tool + * results, assessment-vs-action boundaries, and delegate independent work. + */ +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('Fable 5 overlay — family nudges', () => { + test('raw fable-5.md contains the act-when-ready nudge', () => { + const raw = fs.readFileSync(path.join(ROOT, 'model-overlays/fable-5.md'), 'utf-8'); + expect(raw).toContain('Act when you have enough to act'); + }); + + test('resolved overlay inherits from claude base (INHERIT:claude)', () => { + const out = generateModelOverlay(makeCtx('fable-5')); + expect(out).toContain('Todo-list discipline'); + expect(out).toContain('subordinate'); + }); + + test('resolved overlay carries the Fable nudges', () => { + const out = generateModelOverlay(makeCtx('fable-5')); + expect(out).toContain('Act when you have enough to act'); + expect(out).toContain('Ground progress claims in evidence'); + }); + + test('resolved overlay has no unresolved INHERIT directive', () => { + const out = generateModelOverlay(makeCtx('fable-5')); + expect(out).not.toContain('{{INHERIT:'); + }); + + test('claude overlay (base) does not carry the Fable nudge', () => { + const out = generateModelOverlay(makeCtx('claude')); + expect(out).not.toContain('Act when you have enough to act'); + }); +});