// Actual CLI inference, no HTTP listener and no browser required. import assert from 'node:assert/strict'; import { spawnSync } from 'node:child_process'; import { readFile, writeFile, mkdir } from 'node:fs/promises'; import { fileURLToPath } from 'node:url'; import { resolve, join } from 'node:path'; import { digest } from '../src/core.mjs'; const root = fileURLToPath(new URL('../', import.meta.url)); const out = resolve(process.argv[2] || join(root, 'evidence/cli-demo')); const input = join(root, 'data/sample.json'); const before = await readFile(input); await mkdir(out, { recursive: true }); function infer(filename) { const run = spawnSync(process.execPath, [join(root, 'scripts/triage.mjs'), input, filename], { cwd: root, encoding: 'utf8', timeout: 60000, maxBuffer: 1024 * 1024, }); if (run.error || run.status !== 0) throw new Error(run.error?.message || run.stderr.trim() || `CLI exited ${run.status}`); return { stdout: run.stdout.trim(), stderr: run.stderr.trim() }; } const firstLog = infer(join(out, 'first.json')); const repeatLog = infer(join(out, 'repeat.json')); const first = JSON.parse(await readFile(join(out, 'first.json'), 'utf8')); const repeat = JSON.parse(await readFile(join(out, 'repeat.json'), 'utf8')); const expectedSteps = ['validate-export', 'embed-locally', 'compare-and-abstain', 'build-review-queue']; for (const result of [first, repeat]) { assert.equal(result.execution.status, 'success'); assert.equal(result.model.dimensions, 384); assert.equal(result.model.offline, true); assert.deepEqual(result.workflowSteps, expectedSteps); for (const id of expectedSteps) assert(result.execution.steps.some(step => step.id === id && step.status === 'success')); } const stable = value => value.items.map(({ id, suggestedLabel, needsReview, duplicateOf, similarity }) => ({ id, suggestedLabel, needsReview, duplicateOf, similarity })); assert.deepEqual(stable(first), stable(repeat)); assert.deepEqual(await readFile(input), before); const report = { recordedAtUtc: new Date().toISOString(), kind: 'Two real CLI subprocesses; synthetic input; no listener or browser', command: 'node scripts/triage.mjs data/sample.json OUTPUT.json', summary: first.summary, workflowSteps: expectedSteps, model: first.model, firstProcessTimings: first.timings, repeatProcessTimings: repeat.timings, interpretation: 'Separate same-machine processes; filesystem cache may be warm. These are not cold-machine benchmarks.', inputSha256: digest(JSON.parse(before.toString('utf8'))), originalFileUnchanged: true, decisionsAndScoresRepeatedExactly: true, networkCheck: 'The executed CLI replaces JavaScript fetch with a throwing function. This is an application-level check, not an OS air gap.', logs: { first: firstLog, repeat: repeatLog }, limits: ['All data is synthetic.', 'No measured human time saved.', 'No real browser/UI test or video was recorded.'], }; await writeFile(join(out, 'report.json'), JSON.stringify(report, null, 2) + '\n'); console.log(JSON.stringify({ ...report, logs: undefined, evidenceDirectory: out }, null, 2));