test: remaining SKILL.md-only negatives read the shared preamble too (ship review pass 3)

The parameterized external-host path-leak smoke test, the two Codex
.claude path checks and both vestigial-handshake negatives read SKILL.md
alone, so text that moved into sections/preamble.md went unchecked. They
now read readSkillStartup. preamble.ts's header no longer says tier 1
renders through generatePreamble().

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-10-26 13:20:55 +00:00
1 parent 4510ad3e63
commit 8527857e11
2 files changed
+10 -10

No files matched your search

+5 -5
View File
@@ -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
+5 -5
View File
@@ -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++;
}