diff --git a/scripts/package-artifacts.mjs b/scripts/package-artifacts.mjs index c687326f..635af69d 100644 --- a/scripts/package-artifacts.mjs +++ b/scripts/package-artifacts.mjs @@ -992,6 +992,27 @@ try { requireOutput('ktx runtime stop', runtimeStop, /Stopped KTX Python daemon/); process.stdout.write('ktx runtime daemon lifecycle verified\\n'); + const staleRuntimeDir = join(process.env.KTX_RUNTIME_ROOT, '0.0.0'); + await mkdir(staleRuntimeDir, { recursive: true }); + + const runtimePruneDryRun = await run('pnpm', ['exec', 'ktx', 'runtime', 'prune', '--dry-run']); + requireSuccess('ktx runtime prune dry run', runtimePruneDryRun); + requireOutput('ktx runtime prune dry run', runtimePruneDryRun, /Stale KTX Python runtimes/); + requireOutput('ktx runtime prune dry run', runtimePruneDryRun, /0\\.0\\.0/); + await access(staleRuntimeDir); + + const runtimePruneNeedsConfirmation = await run('pnpm', ['exec', 'ktx', 'runtime', 'prune']); + assert.equal(runtimePruneNeedsConfirmation.code, 1, 'ktx runtime prune needs confirmation'); + assert.equal(runtimePruneNeedsConfirmation.stdout, '', 'ktx runtime prune needs confirmation wrote stdout'); + assert.match(runtimePruneNeedsConfirmation.stderr, /Refusing to prune without --yes/); + + const runtimePruneConfirmed = await run('pnpm', ['exec', 'ktx', 'runtime', 'prune', '--yes']); + requireSuccess('ktx runtime prune confirmed', runtimePruneConfirmed); + requireOutput('ktx runtime prune confirmed', runtimePruneConfirmed, /Removed stale KTX Python runtimes/); + requireOutput('ktx runtime prune confirmed', runtimePruneConfirmed, /0\\.0\\.0/); + await assert.rejects(() => access(staleRuntimeDir)); + process.stdout.write('ktx runtime prune verified\\n'); + const structuralScan = await run('pnpm', ['exec', 'ktx', 'dev', 'scan', 'warehouse', '--project-dir', projectDir, diff --git a/scripts/package-artifacts.test.mjs b/scripts/package-artifacts.test.mjs index b5a190f7..de051d59 100644 --- a/scripts/package-artifacts.test.mjs +++ b/scripts/package-artifacts.test.mjs @@ -583,6 +583,13 @@ describe('verification snippets', () => { assert.match(source, /ktx runtime start reuse/); assert.match(source, /Using existing KTX Python daemon/); assert.match(source, /ktx runtime stop/); + assert.match(source, /ktx runtime prune dry run/); + assert.match(source, /0\.0\.0/); + assert.match(source, /ktx runtime prune needs confirmation/); + assert.match(source, /Refusing to prune without --yes/); + assert.match(source, /ktx runtime prune confirmed/); + assert.match(source, /Removed stale KTX Python runtimes/); + assert.match(source, /assert\.rejects\(\(\) => access\(staleRuntimeDir\)\)/); assert.match(source, /run\('pnpm', \[\s*'exec',\s*'ktx',\s*'dev',\s*'scan',\s*'warehouse'/); assert.match(source, /'--mode',\s*'enriched'/); assert.doesNotMatch(source, /'--enrich'/);