import { mkdtemp, mkdir, readFile, rm, writeFile, symlink } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' import yaml from 'js-yaml' import { discoverAtoms } from '../lib/atom-discovery' import { buildMigrationSql } from '../generate-skill-bodies' import { publicSkillFiles, stampMit, syncPublicSkills } from '../sync-public-skills' const directories: string[] = [] async function directory() { const dir = await mkdtemp(join(tmpdir(), 'accounted-skills-test-')); directories.push(dir); return dir } afterEach(async () => { for (const dir of directories.splice(0)) await rm(dir, { recursive: true, force: true }) }) async function fixture(root: string, slug: string, body: string, extra: Record = {}) { await mkdir(join(root, '.claude/skills'), { recursive: true }) await mkdir(join(root, 'registry/entries'), { recursive: true }) await mkdir(join(root, `registry/skills/${slug}`), { recursive: true }) await writeFile(join(root, `registry/entries/${slug}.mdx`), `---\n${yaml.dump({ slug, title: slug, description: 'Reviewed workflow', kind: 'skill', status: 'live', mcp_exposed: true, reviewedAt: '2026-09-17', ...extra })}---\n\nDescription.\n`) await writeFile(join(root, `registry/skills/${slug}/SKILL.md`), body) } describe('reviewed community generation', () => { it('seeds developer and firm submissions through the same generator', async () => { const root = await directory() await fixture(root, 'developer-workflow', 'Review the selected transactions.') await fixture(root, 'firm-workflow', 'Use the approved company mappings.', { submissionHash: 'reviewed-frozen-hash', author: 'firm-author' }) const atoms = await discoverAtoms(root) expect(atoms.map((atom) => atom.id)).toEqual(['community/developer-workflow', 'community/firm-workflow']) expect(atoms.every((atom) => atom.mcp_exposed && atom.reviewed_at === '2026-09-17')).toBe(true) const sql = buildMigrationSql(atoms, Object.fromEntries(atoms.map((atom) => [atom.id, 1]))) expect(sql).toContain('Review the selected transactions.') expect(sql).toContain('Use the approved company mappings.') }) it('requires reviewer metadata before MCP exposure', async () => { const root = await directory() await fixture(root, 'unreviewed', 'Body', { reviewedAt: undefined }) await expect(discoverAtoms(root)).rejects.toThrow('reviewedAt') }) it('rejects raw tags in the loadable body, not only the registry description', async () => { const root = await directory() await fixture(root, 'unsafe', '') await expect(discoverAtoms(root)).rejects.toThrow('plain Markdown') }) it('does not expose archived entries', async () => { const root = await directory() await fixture(root, 'archived', 'Body', { status: 'archived' }) expect((await discoverAtoms(root))[0].mcp_exposed).toBe(false) }) }) describe('public mirror', () => { it('stamps MIT without breaking frontmatter', () => { const body = '---\nname: swedish-test\n---\n# Test\n' expect(stampMit(body)).toMatch(/^---\nname: swedish-test\n---\n