diff --git a/test/cso-spec-taxonomy-alignment.test.ts b/test/cso-spec-taxonomy-alignment.test.ts index 4d23748ce..76ba36518 100644 --- a/test/cso-spec-taxonomy-alignment.test.ts +++ b/test/cso-spec-taxonomy-alignment.test.ts @@ -14,7 +14,20 @@ import { HOST_PATHS } from "../scripts/resolvers/types"; import { PATTERNS } from "../lib/redact-patterns"; const ROOT = path.resolve(import.meta.dir, ".."); -const CSO = fs.readFileSync(path.join(ROOT, "cso", "SKILL.md"), "utf-8"); +// cso is carved (skeleton + sections/audit-phases.md). The Secrets Archaeology +// prose + secret prefixes moved into the section; check the union so relocated +// content still counts. +function unionSkill(skill: string): string { + let t = fs.readFileSync(path.join(ROOT, skill, "SKILL.md"), "utf-8"); + const dir = path.join(ROOT, skill, "sections"); + if (fs.existsSync(dir)) { + for (const f of fs.readdirSync(dir).sort()) { + if (f.endsWith(".md") && !f.endsWith(".md.tmpl")) t += "\n" + fs.readFileSync(path.join(dir, f), "utf-8"); + } + } + return t; +} +const CSO = unionSkill("cso"); const ctx = { skillName: "cso", tmplPath: "", host: "claude" as const, paths: HOST_PATHS["claude"] }; describe("cso/spec taxonomy alignment", () => { diff --git a/test/document-skills-redaction.test.ts b/test/document-skills-redaction.test.ts index 235d7895b..00ab85e0d 100644 --- a/test/document-skills-redaction.test.ts +++ b/test/document-skills-redaction.test.ts @@ -6,7 +6,21 @@ import * as fs from "fs"; import * as path from "path"; const ROOT = path.resolve(import.meta.dir, ".."); -const RELEASE = fs.readFileSync(path.join(ROOT, "document-release", "SKILL.md.tmpl"), "utf-8"); +// document-release is carved (skeleton + sections/release-body.md). Step 9 +// (commit + PR-body redaction scan) moved into the section template; check the +// union of SKILL.md.tmpl + sections/*.md.tmpl so the scan-before-edit ordering +// still verifies. document-generate is NOT carved (plain .md.tmpl). +function unionTmpl(skill: string): string { + let t = fs.readFileSync(path.join(ROOT, skill, "SKILL.md.tmpl"), "utf-8"); + const dir = path.join(ROOT, skill, "sections"); + if (fs.existsSync(dir)) { + for (const f of fs.readdirSync(dir).sort()) { + if (f.endsWith(".md.tmpl")) t += "\n" + fs.readFileSync(path.join(dir, f), "utf-8"); + } + } + return t; +} +const RELEASE = unionTmpl("document-release"); const GENERATE = fs.readFileSync(path.join(ROOT, "document-generate", "SKILL.md.tmpl"), "utf-8"); describe("/document-release redaction", () => { diff --git a/test/spec-template-invariants.test.ts b/test/spec-template-invariants.test.ts index 262bba520..ab95c2c9b 100644 --- a/test/spec-template-invariants.test.ts +++ b/test/spec-template-invariants.test.ts @@ -111,7 +111,16 @@ describe('/spec quality gate fallback', () => { describe('/spec fail-closed redaction (shared engine)', () => { test('the full taxonomy (with secret prefixes) lives in the generated /cso doc', () => { - const cso = fs.readFileSync(path.join(ROOT, 'cso', 'SKILL.md'), 'utf-8'); + // cso is carved — the Secrets Archaeology prose + prefixes moved into + // sections/audit-phases.md; read the skeleton+sections union. + const csoDir = path.join(ROOT, 'cso'); + let cso = fs.readFileSync(path.join(csoDir, 'SKILL.md'), 'utf-8'); + const secDir = path.join(csoDir, 'sections'); + if (fs.existsSync(secDir)) { + for (const f of fs.readdirSync(secDir).sort()) { + if (f.endsWith('.md') && !f.endsWith('.md.tmpl')) cso += '\n' + fs.readFileSync(path.join(secDir, f), 'utf-8'); + } + } expect(cso).toContain('AKIA'); expect(cso).toMatch(/ghp_|gho_|ghs_/); expect(cso).toContain('sk-ant-');