import assert from 'node:assert/strict' import { spawnSync } from 'node:child_process' import { cpSync, readFileSync } from 'node:fs' import { dirname, join, resolve } from 'node:path' import test from 'node:test' import { fileURLToPath } from 'node:url' import { cleanup, tempDir, write } from './helpers.mjs' const testDir = dirname(fileURLToPath(import.meta.url)) const repoRoot = resolve(testDir, '..', '..') const syncScript = resolve(repoRoot, 'dsh/sync/sync-from-upstream.mjs') const verifyScript = resolve(repoRoot, 'dsh/sync/verify-skills.mjs') const fixture = resolve(testDir, 'fixtures', 'superpowers-min') function run(script, args) { return spawnSync(process.execPath, [script, ...args], { encoding: 'utf8' }) } /** * The tree every test starts from: Task 1's sync applied to the reduced * upstream checkout — 15 skill directories plus the DSH `dsh-tools.md` * override. Verify only ever sees a synced tree, never raw upstream text. */ function syncedTree(work) { const out = join(work, 'synced') const result = run(syncScript, [fixture, '--out', out, '--ref', 'v7.0.1']) assert.equal(result.status, 0, `sync fixture failed: ${result.stderr}`) return out } /** A private copy of a synced tree: the failing tests mutate it. */ function syncedCopy(work, dir) { const copy = join(work, 'copy') cpSync(dir, copy, { recursive: true }) return copy } function verify(dir) { return run(verifyScript, [dir]) } test('verify ok on synced tree', () => { const work = tempDir('dsh-verify-ok-') try { const result = verify(syncedTree(work)) assert.equal(result.status, 0, `stderr: ${result.stderr}`) assert.match(result.stdout, /^ok: using-superpowers$/m) assert.match(result.stdout, /verified 15 skills/) assert.equal((result.stdout.match(/^ok: /gm) ?? []).length, 15, 'one ok line per skill directory') } finally { cleanup(work) } }) test('verify fails on missing description', () => { const work = tempDir('dsh-verify-no-description-') try { const dir = syncedCopy(work, syncedTree(work)) const file = join(dir, 'brainstorming', 'SKILL.md') write(file, readFileSync(file, 'utf8').replace(/^description:.*\n/m, '')) const result = verify(dir) assert.equal(result.status, 1) assert.match(result.stderr, /brainstorming\/SKILL\.md/) assert.match(result.stderr, /description/) } finally { cleanup(work) } }) test('verify fails on leftover superpowers: prefix in a body', () => { const work = tempDir('dsh-verify-prefix-') try { const dir = syncedCopy(work, syncedTree(work)) const file = join(dir, 'systematic-debugging', 'SKILL.md') write(file, `${readFileSync(file, 'utf8')}\nSee superpowers:brainstorming for the upstream wording.\n`) const result = verify(dir) assert.equal(result.status, 1) assert.match(result.stderr, /systematic-debugging\/SKILL\.md/) assert.match(result.stderr, /superpowers:/) } finally { cleanup(work) } }) test('verify fails on dangling relative reference', () => { const work = tempDir('dsh-verify-dangling-') try { const dir = syncedCopy(work, syncedTree(work)) const file = join(dir, 'writing-plans', 'SKILL.md') write(file, `${readFileSync(file, 'utf8')}\nSee [the missing file](../brainstorming/nope.md).\n`) const result = verify(dir) assert.equal(result.status, 1) assert.match(result.stderr, /writing-plans\/SKILL\.md/) assert.match(result.stderr, /\.\.\/brainstorming\/nope\.md/) } finally { cleanup(work) } }) test('verify ignores illustrative example script paths', () => { const work = tempDir('dsh-verify-illustrative-') try { const dir = syncedCopy(work, syncedTree(work)) const file = join(dir, 'writing-skills', 'SKILL.md') write( file, `${readFileSync(file, 'utf8')}\nInvoke bundled scripts in prose: \`bash scripts/tool.sh\`, \`node scripts/tool.js\`.\n`, ) const result = verify(dir) assert.equal(result.status, 0, `stderr: ${result.stderr}`) assert.match(result.stdout, /verified 15 skills/) } finally { cleanup(work) } }) test('verify ok when superpowers: survives in a references file (T1.5)', () => { const work = tempDir('dsh-verify-references-') try { const dir = syncedTree(work) const reference = readFileSync(join(dir, 'using-superpowers', 'references', 'dsh-tools.md'), 'utf8') assert.match(reference, /superpowers:/, 'the DSH tool mapping quotes the upstream namespace on purpose') const result = verify(dir) assert.equal(result.status, 0, `stderr: ${result.stderr}`) assert.match(result.stdout, /verified 15 skills/) } finally { cleanup(work) } })