// Step 9 test — the thin-catalog state (against a workspace copy): // - no plugins/, no shared/, no scripts/sync-design-system.mjs (SC4) // - CONVENTIONS.md exists + carries the Forgejo / conventional-commits / three-doc rules (D6) // - marketplace.json + README.md + GOVERNANCE.md remain // - the rewritten README has zero local plugins//shared/ links and uses external Forgejo repos // - the stale playground-design-system version is corrected from plugin-map (v0.6.0) // Pattern: plugins/config-audit/tests/*.test.mjs. import test from 'node:test'; import assert from 'node:assert/strict'; import { spawnSync } from 'node:child_process'; import { mkdtempSync, rmSync, existsSync, readFileSync } from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const here = path.dirname(fileURLToPath(import.meta.url)); const SCRIPT = path.join(here, '70-thin-catalog.sh'); function thin() { const ws = mkdtempSync(path.join(os.tmpdir(), 'thin-catalog-')); const r = spawnSync('bash', [SCRIPT, '--workspace', ws], { encoding: 'utf8' }); return { ws, r }; } test('removes plugins/, shared/, and scripts/sync-design-system.mjs (SC4)', () => { const { ws, r } = thin(); try { assert.equal(r.status, 0, `expected exit 0:\n${r.stdout}\n${r.stderr}`); assert.ok(!existsSync(path.join(ws, 'plugins')), 'plugins/ must be gone'); assert.ok(!existsSync(path.join(ws, 'shared')), 'shared/ must be gone'); assert.ok(!existsSync(path.join(ws, 'scripts', 'sync-design-system.mjs')), 'sync-design-system.mjs must be gone'); } finally { rmSync(ws, { recursive: true, force: true }); } }); test('CONVENTIONS.md exists and carries Forgejo / conventional-commits / three-doc rules', () => { const { ws, r } = thin(); try { assert.equal(r.status, 0, r.stderr); const conv = path.join(ws, 'CONVENTIONS.md'); assert.ok(existsSync(conv), 'CONVENTIONS.md must exist'); const text = readFileSync(conv, 'utf8'); assert.match(text, /Forgejo/, 'must carry the Forgejo rule'); assert.match(text, /Conventional Commits/, 'must carry the conventional-commits rule'); assert.match(text, /tre doc-nivåer/, 'must carry the three-doc rule'); } finally { rmSync(ws, { recursive: true, force: true }); } }); test('marketplace.json, README.md, GOVERNANCE.md remain', () => { const { ws, r } = thin(); try { assert.equal(r.status, 0, r.stderr); assert.ok(existsSync(path.join(ws, '.claude-plugin', 'marketplace.json')), 'marketplace.json must remain'); assert.ok(existsSync(path.join(ws, 'README.md')), 'README.md must remain'); assert.ok(existsSync(path.join(ws, 'GOVERNANCE.md')), 'GOVERNANCE.md must remain'); } finally { rmSync(ws, { recursive: true, force: true }); } }); test('rewritten README has no local plugins//shared/ links and corrects the DS version (M15)', () => { const { ws, r } = thin(); try { assert.equal(r.status, 0, r.stderr); const readme = readFileSync(path.join(ws, 'README.md'), 'utf8'); assert.ok(!/\]\(plugins\//.test(readme), 'no local plugins/ links may remain'); assert.ok(!/\]\(shared\//.test(readme), 'no local shared/ links may remain'); assert.match(readme, /https:\/\/git\.fromaitochitta\.com\/open\//, 'must reference external Forgejo repos'); // playground-design-system was stale at v0.1 in the live README; plugin-map pins v0.6.0 assert.ok(!/`v0\.1`/.test(readme), 'stale playground-design-system v0.1 must be corrected'); assert.match(readme, /`v0\.6\.0`/, 'playground-design-system must read v0.6.0 from plugin-map'); } finally { rmSync(ws, { recursive: true, force: true }); } });