Generate degraded-mode fallback references from the subagent definitions

Harnesses with no subagent capability now run each role inline from the
same single source. The build emits reference/degraded/<role>.md for every
agent in skill/agents/ (role name is the agent name minus the impeccable-
prefix), stripping frontmatter and prepending the inline-substitution
preamble. These pass through the same provider-block compilation and
placeholder replacement as ordinary reference files, so <codex> blocks and
{{placeholders}} resolve per target, and they land in the committed harness
dirs on build:release like every reference file.

Repoint the three capability-first fallback sites in the prose at the
generated files: new-work.md reviewer and documenter fallbacks, and
visualize.md asset-producer fallback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-07-25 19:16:17 -07:00
co-authored by Claude Fable 5
parent 6769b1879a
commit 916b0a1fdf
4 changed files with 111 additions and 3 deletions
+28
View File
@@ -13,6 +13,12 @@ import {
import { SKILL_CATEGORIES, CATEGORY_ORDER } from '../skill-categories.js';
import { hooksJsonFor } from './hooks.js';
// Preamble prepended to every generated degraded-mode fallback reference file.
// These files are single-sourced from skill/agents/ so a harness with no
// subagent capability runs each role inline from the same specialized text.
const DEGRADED_PREAMBLE = `<!-- Generated from skill/agents/ at build time. Do not edit; edit the agent definition. -->
This harness has no subagent capability, so you are running this role inline. Step fully out of the work you just finished, adopt only this file's instructions for the pass, and disclose the substitution in one line when you report. Where the text below addresses a parent agent, you are both parties: produce the full output contract first, then act on it yourself.`;
/**
* Map from frontmatter field name to extraction spec.
*
@@ -258,6 +264,28 @@ export function createTransformer(config) {
}
}
// Generate degraded-mode fallback reference files from the shipped
// subagent definitions. Single-sourced from skill/agents/ so a harness
// with no subagent capability runs each role inline from the same
// specialized text. Role name = agent name minus the `impeccable-`
// prefix. These pass through the same provider-block compilation and
// placeholder replacement as ordinary reference files, so <codex> blocks
// and {{placeholders}} resolve identically.
if (skill.agents && skill.agents.length > 0) {
const degradedDir = path.join(skillDir, 'reference', 'degraded');
ensureDir(degradedDir);
for (const agent of skill.agents) {
const role = agent.name.replace(/^impeccable-/, '');
let body = compileProviderBlocks(agent.body, providerTags);
body = replacePlaceholders(body, placeholderKey, [], allSkillNames);
body = stripRuleMarkers(body);
body = body.replace(/\{\{scripts_path\}\}/g, scriptsPath);
const content = `${DEGRADED_PREAMBLE}\n\n${body.replace(/^\s+/, '')}`;
writeFile(path.join(degradedDir, `${role}.md`), content);
refCount++;
}
}
// Copy script files
if (skill.scripts && skill.scripts.length > 0) {
const scriptsOutDir = path.join(skillDir, 'scripts');
+2 -2
View File
@@ -102,6 +102,6 @@ Preserve semantics, accessibility, performance, responsiveness, project conventi
Inspect desktop and mobile in one batched screenshot round, critique the render against the user's request and the direction contract, fix material gaps, and confirm with one final round; two rounds is the ceiling, and fixes batch between them rather than earning per-tweak screenshots. On a Persuade surface, verify the mode did its job: a first-time visitor should know what this is, why it matters, and what to do within seconds, in the form's own vocabulary.
After the second inspection round the build thread's polishing is over: no further defect hunts, micro-edit scripts, or rebuilds here; whatever remains ships through the handoffs, where a fresh context does the finding better and cheaper. Capture desktop and mobile screenshots to files, then spawn the shipped finish reviewer, `impeccable-finish-reviewer` (`impeccable_finish_reviewer` in codex), with the original request, confirmed answers, the artifact path, the screenshot paths, its direction contract, existing hook findings, and the QUALITY BAR card and approved comp paths. The reviewer has no browser; screenshots you fail to pass are checks it cannot run. Verify its return carries the five contract sections; on an empty or thrashed return, respawn once with the same inputs before doing anything else. This review never runs inside the build thread. Only a harness whose tool surface has no subagent capability at all substitutes a fresh in-thread pass after stepping fully out of the build context, and a substituted or failed-and-replaced review is disclosed in one line at finish, never silently. Apply the material fixes in one batch, rebuild once, and stop; the reviewer ran so that you do not re-open your own hunt. Do not run a second detector. <!-- rule:skill-finish-separate-reviewer -->
After the second inspection round the build thread's polishing is over: no further defect hunts, micro-edit scripts, or rebuilds here; whatever remains ships through the handoffs, where a fresh context does the finding better and cheaper. Capture desktop and mobile screenshots to files, then spawn the shipped finish reviewer, `impeccable-finish-reviewer` (`impeccable_finish_reviewer` in codex), with the original request, confirmed answers, the artifact path, the screenshot paths, its direction contract, existing hook findings, and the QUALITY BAR card and approved comp paths. The reviewer has no browser; screenshots you fail to pass are checks it cannot run. Verify its return carries the five contract sections; on an empty or thrashed return, respawn once with the same inputs before doing anything else. This review never runs inside the build thread. Only a harness whose tool surface has no subagent capability at all substitutes a fresh in-thread pass after stepping fully out of the build context, run from [degraded/finish-reviewer.md](degraded/finish-reviewer.md), and a substituted or failed-and-replaced review is disclosed in one line at finish, never silently. Apply the material fixes in one batch, rebuild once, and stop; the reviewer ran so that you do not re-open your own hunt. Do not run a second detector. <!-- rule:skill-finish-separate-reviewer -->
Then spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, the artifact path, the direction contract, PRODUCT.md, the [document.md](document.md) reference path, and the boundary to write at; it records DESIGN.md and the sidecar from the built world, ground truth over intention. A clean detector pass is not finished; finished is the contract kept, the comp honored, the review closed, and the system recorded. <!-- rule:skill-documenter-records-the-world -->
Then spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, the artifact path, the direction contract, PRODUCT.md, the [document.md](document.md) reference path, and the boundary to write at; it records DESIGN.md and the sidecar from the built world, ground truth over intention; without subagents the pass runs from [degraded/documenter.md](degraded/documenter.md). A clean detector pass is not finished; finished is the contract kept, the comp honored, the review closed, and the system recorded. <!-- rule:skill-documenter-records-the-world -->
+1 -1
View File
@@ -33,6 +33,6 @@ Treat the comp as a north star, not something to trace. Do not rasterize core UI
## Produce only the assets the build needs
When clean raster ingredients are required and the harness runs subagents, use the shipped asset producer, `impeccable-asset-producer` (`impeccable_asset_producer` in codex): give it the approved comp, output paths, required dimensions and formats, transparency needs, crop notes, and what must remain semantic code. Otherwise produce the minimum required assets in the current thread with whatever generation exists, the native tool or generate-image.mjs.
When clean raster ingredients are required and the harness runs subagents, use the shipped asset producer, `impeccable-asset-producer` (`impeccable_asset_producer` in codex): give it the approved comp, output paths, required dimensions and formats, transparency needs, crop notes, and what must remain semantic code. Otherwise produce the minimum required assets in the current thread by the book: load [degraded/asset-producer.md](degraded/asset-producer.md) and follow it inline, with whatever generation exists, the native tool or generate-image.mjs.
Return to [new-work.md](new-work.md) for the direction contract, implementation, and the finishing pass.
+80
View File
@@ -386,3 +386,83 @@ describe('bundled skill scripts are self-contained', () => {
expect(broken).toEqual([]);
});
});
describe('degraded-mode fallback reference generation', () => {
const ROOT = process.cwd();
const DEGRADED_TEST_DIR = path.join(ROOT, 'test-tmp-degraded');
const DIST = path.join(DEGRADED_TEST_DIR, 'dist');
const readDegraded = (provider, configDir, role) =>
fs.readFileSync(
path.join(DIST, provider, configDir, 'skills', 'impeccable', 'reference', 'degraded', `${role}.md`),
'utf-8'
);
beforeEach(() => {
if (fs.existsSync(DEGRADED_TEST_DIR)) fs.rmSync(DEGRADED_TEST_DIR, { recursive: true, force: true });
fs.mkdirSync(DEGRADED_TEST_DIR, { recursive: true });
const { skills } = utils.readSourceFiles(ROOT);
transformers.transformClaudeCode(skills, DIST);
transformers.transformCodex(skills, DIST);
});
afterEach(() => {
if (fs.existsSync(DEGRADED_TEST_DIR)) fs.rmSync(DEGRADED_TEST_DIR, { recursive: true, force: true });
});
test('a build emits reference/degraded/<role>.md for every agent, prefix-stripped', () => {
const dir = path.join(DIST, 'codex', '.codex', 'skills', 'impeccable', 'reference', 'degraded');
const files = fs.readdirSync(dir).sort();
expect(files).toEqual([
'asset-producer.md',
'documenter.md',
'finish-reviewer.md',
'manual-edit-applier.md',
]);
});
test('finish-reviewer fallback opens with the preamble and carries a distinctive body phrase', () => {
const content = readDegraded('codex', '.codex', 'finish-reviewer');
expect(content.startsWith('<!-- Generated from skill/agents/ at build time. Do not edit; edit the agent definition. -->'))
.toBe(true);
expect(content).toContain('This harness has no subagent capability, so you are running this role inline.');
// Distinctive phrase from the agent body proves the source body was inlined.
expect(content).toContain('material_fixes');
});
test('generated fallbacks pass through provider-block compilation (codex keeps its block, others strip it)', () => {
// Standalone provider blocks are the shape compileProviderBlocks compiles.
// A synthetic agent proves the degraded path runs the same compilation as
// ordinary reference files, with the right provider tags per target.
const synthetic = {
name: 'impeccable',
description: 'synthetic',
body: 'Synthetic skill body.',
agents: [
{
name: 'impeccable-synthetic',
body: 'Shared body line.\n\n<codex>\nCODEX_ONLY_MARKER for the codex target.\n</codex>\n\nMore shared body.',
},
],
};
const synthDist = path.join(DEGRADED_TEST_DIR, 'synth');
transformers.transformCodex([synthetic], synthDist);
transformers.transformClaudeCode([synthetic], synthDist);
const read = (provider, configDir) =>
fs.readFileSync(
path.join(synthDist, provider, configDir, 'skills', 'impeccable', 'reference', 'degraded', 'synthetic.md'),
'utf-8'
);
const codex = read('codex', '.codex');
const claude = read('claude-code', '.claude');
expect(codex).toContain('CODEX_ONLY_MARKER');
expect(claude).not.toContain('CODEX_ONLY_MARKER');
// Both still carry the preamble and the shared body.
expect(codex.startsWith('<!-- Generated from skill/agents/')).toBe(true);
expect(claude).toContain('More shared body.');
});
test('the source repo contains no hand-authored degraded/ reference files (generation-only)', () => {
expect(fs.existsSync(path.join(ROOT, 'skill', 'reference', 'degraded'))).toBe(false);
});
});