diff --git a/scripts/resolvers/preamble.ts b/scripts/resolvers/preamble.ts index 07183bdcb..c39da2f2b 100644 --- a/scripts/resolvers/preamble.ts +++ b/scripts/resolvers/preamble.ts @@ -3,11 +3,11 @@ * * Each generator lives in its own file under ./preamble/*.ts. This file only * wires them together: preambleSections() is the composition, and - * generatePreamble() joins it into the full inline render (tier 1 skills and - * the tests' oracle). For tier 2+ skills, {{PREAMBLE}} resolves through - * ./preamble-hoist.ts, which splits the same sections into a per-skill pointer - * plus the shared sections/preamble.md the skill Reads on load. Keep - * composition declarative — no inline logic beyond tier gating. + * generatePreamble() joins it into the full inline render that tests use as + * the pre-hoist oracle. {{PREAMBLE}} resolves through ./preamble-hoist.ts, + * which renders tier 1 inline and splits tier 2+ into a per-skill pointer plus + * the shared sections/preamble.md the skill Reads on load. Keep composition + * declarative — no inline logic beyond tier gating. * * Each skill runs independently via `claude -p` (or the host's equivalent). * The preamble provides: update checks, session diff --git a/test/gen-skill-docs.test.ts b/test/gen-skill-docs.test.ts index 057bafe32..46140288f 100644 --- a/test/gen-skill-docs.test.ts +++ b/test/gen-skill-docs.test.ts @@ -2945,14 +2945,14 @@ describe('Codex generation (--host codex)', () => { test('no .claude/skills/ in Codex output', () => { for (const skill of CODEX_SKILLS) { - const content = fs.readFileSync(path.join(AGENTS_DIR, skill.codexName, 'SKILL.md'), 'utf-8'); + const content = readSkillStartup(path.join(AGENTS_DIR, skill.codexName, 'SKILL.md')); expect(content).not.toContain('.claude/skills'); } }); test('no ~/.claude/ runtime paths in Codex output', () => { for (const skill of CODEX_SKILLS) { - const content = fs.readFileSync(path.join(AGENTS_DIR, skill.codexName, 'SKILL.md'), 'utf-8'); + const content = readSkillStartup(path.join(AGENTS_DIR, skill.codexName, 'SKILL.md')); // Outside prompts may explicitly forbid reading Claude's skill directory. // Every executable/runtime path must still use the selected host root. const withoutBoundary = content.replace(/^.*do not read or execute any files under[^\n]*$/gim, ''); @@ -3437,7 +3437,7 @@ describe('Parameterized host smoke tests', () => { if (isRepoRootSymlink(path.join(hostDir, skill))) continue; const skillMd = path.join(hostDir, skill, 'SKILL.md'); if (!fs.existsSync(skillMd)) continue; - const content = fs.readFileSync(skillMd, 'utf-8'); + const content = readSkillStartup(skillMd); const leaks = externalHostPathLeaks(content); if (leaks.length > 0) { throw new Error(`${skill}: .claude/skills leakage:\n${leaks.slice(0, 3).join('\n')}`); @@ -4578,7 +4578,7 @@ describe('plan-mode-info resolver (handshake-replacement)', () => { if (!entry.isDirectory()) continue; const skillMd = path.join(ROOT, entry.name, 'SKILL.md'); if (!fs.existsSync(skillMd)) continue; - const content = fs.readFileSync(skillMd, 'utf-8'); + const content = readSkillStartup(skillMd); expect(content, `handshake marker in ${entry.name}/SKILL.md`).not.toContain(HANDSHAKE_MARKER); checked++; } @@ -4601,7 +4601,7 @@ describe('plan-mode-info resolver (handshake-replacement)', () => { if (!entry.isDirectory()) continue; const skillMd = path.join(skillsRoot, entry.name, 'SKILL.md'); if (!fs.existsSync(skillMd)) continue; - const content = fs.readFileSync(skillMd, 'utf-8'); + const content = readSkillStartup(skillMd); expect(content, `handshake marker in ${host}/skills/${entry.name}/SKILL.md`).not.toContain(HANDSHAKE_MARKER); checked++; }