// Step 11 test — the full local dry-run report ($WORK/dryrun-report.md) + previews. // Verifies the GENERATED artifact (does not re-derive it): // - the report lists all 11 targets // - voyage shows >=250 commits (F1 — pre-rename history retained) // - config-audit shows PASS under its dedicated SC2 gate (50-config-audit-sc2.sh) // - llm-security shows complete content retention (SC6 — no file DROP; the dual-rename defect is fixed) // - no SC6 DROP and no SC2 regression on ANY target // - no target shows a tracked state-file leak (SC7) // - the previewed all-external marketplace.json has zero ./plugins/ and zero ssh:// (F2) // Pattern: plugins/voyage/tests/integration/*.test.mjs (heavy integration — long timeout, artifact reuse). import test from 'node:test'; import assert from 'node:assert/strict'; import { spawnSync } from 'node:child_process'; import { existsSync, readFileSync } from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const here = path.dirname(fileURLToPath(import.meta.url)); const SCRIPT = path.join(here, '99-dryrun.sh'); const WORK = process.env.WORK || '/tmp/polyrepo-migration'; const REPORT = path.join(WORK, 'dryrun-report.md'); const MP_PREVIEW = path.join(WORK, 'marketplace.all-external.json'); const LONG = 1000 * 60 * 25; // cold path force-fresh re-extracts 11 repos + runs their suites const TARGETS = [ 'ai-psychosis', 'claude-design', 'config-audit', 'graceful-handoff', 'human-friendly-style', 'linkedin-studio', 'llm-security', 'ms-ai-architect', 'okr', 'playground-design-system', 'voyage', ]; let _report = null; function report() { if (_report !== null) return _report; if (!existsSync(REPORT)) { const r = spawnSync('bash', [SCRIPT], { encoding: 'utf8', timeout: 1000 * 60 * 24, env: { ...process.env, WORK } }); if (!existsSync(REPORT)) { throw new Error(`dry-run did not produce ${REPORT}\nstdout:\n${r.stdout}\nstderr:\n${r.stderr}`); } } _report = readFileSync(REPORT, 'utf8'); return _report; } function row(key) { return report().split('\n').find((l) => new RegExp(`^\\|\\s*${key}\\s*\\|`).test(l)) || ''; } test('report lists all 11 targets', { timeout: LONG }, () => { const r = report(); for (const t of TARGETS) assert.ok(r.includes(t), `report must list target ${t}`); const rows = r.split('\n').filter((l) => /^\|\s*[a-z0-9-]+\s*\|\s*\d+\s*\|/.test(l)); assert.equal(rows.length, 11, `expected 11 target rows, found ${rows.length}`); }); test('voyage shows >=250 commits (F1 pre-rename history retained)', { timeout: LONG }, () => { const m = report().match(/\|\s*voyage\s*\|\s*(\d+)\s*\|/); assert.ok(m, 'voyage row with a commit count must be present'); assert.ok(Number(m[1]) >= 250, `voyage commits ${m && m[1]} must be >= 250`); }); test('config-audit PASSes its dedicated SC2 gate', { timeout: LONG }, () => { const line = row('config-audit'); assert.ok(line, 'config-audit row must be present'); assert.ok(/\bPASS\b/.test(line) && !/FAIL/.test(line), `config-audit must PASS: ${line}`); }); test('llm-security retains all content (SC6 — dual-rename file-drop defect is fixed)', { timeout: LONG }, () => { const line = row('llm-security'); assert.ok(line, 'llm-security row must be present'); assert.ok(!/DROP/.test(line), `llm-security must not drop files (SC6): ${line}`); assert.ok(/\bPASS\b/.test(line) && !/FAIL/.test(line), `llm-security must PASS standalone: ${line}`); }); // This asserts the HAPPY path (the live report shows no DROP / no regression). The NEGATIVE coverage — // proving the SC6 DROP and SC2 regression-FAIL detectors actually FIRE — lives in sc-checks.test.mjs, // which drives sc6-check.sh / sc2-regression.sh (the extracted detectors this dry-run calls) directly, // because force-fresh re-extraction would undo any file-drop planted into $WORK/ here (5d112cb). test('no SC6 file-drop and no SC2 regression on any target', { timeout: LONG }, () => { const r = report(); assert.ok(!/\bDROP\b/.test(r), 'no target may drop content (SC6)'); assert.ok(!/regression:/.test(r), 'no target may show an SC2 regression'); }); test('no target shows a tracked state-file leak (SC7)', { timeout: LONG }, () => { assert.ok(!/LEAK/.test(report()), 'no SC7 state-file leak may appear in the report'); }); test('all-external marketplace.json preview has zero ./plugins/ and zero ssh:// (F2)', { timeout: LONG }, () => { report(); assert.ok(existsSync(MP_PREVIEW), `${MP_PREVIEW} must exist`); const mp = readFileSync(MP_PREVIEW, 'utf8'); assert.ok(!mp.includes('./plugins/'), 'no local ./plugins/ source may remain'); assert.ok(!mp.includes('ssh://'), 'no ssh:// url may remain'); });