import test from 'node:test'; import assert from 'node:assert/strict'; import { coverageBaseline, caseEvidence, canonicalPath } from '../../../tools/web/coverage-baseline.mjs'; import { digest } from '../../../tools/web/workflow-case-lib.mjs'; const sourceHash = digest('source'), proofHash = digest('proof'); const treeHash = digest(`a.cc\0${sourceHash}\n`); test('equivalent absolute and relative input paths have one identity', () => { assert.equal(canonicalPath('/workspace', '/workspace/cases/result.json'), canonicalPath('/workspace', './cases/result.json')); assert.equal(canonicalPath('/workspace', 'cases/../cases/result.json'), 'cases/result.json'); assert.throws(() => canonicalPath('/workspace', 123), /string/); }); const receipt = () => ({ cases: [{ kind: 'minimal', status: 'PASS', inputs: [{ path: 'input', sha256: proofHash }], artifacts: [{ path: 'output', sha256: proofHash }], process: { code: 0, timedOut: false, cancelled: false }, result: { passed: true, tests: 2 } }], remainingGates: ['production'] }); function fixture() { const catalog = { entries: [{ id: 'op:a' }], unitCount: 1 }; const binding = { evidenceManifest: { path: 'manifest', sha256: proofHash }, productionEvidence: { path: 'production', sha256: proofHash }, sourceTreeSha256: treeHash }; const inventory = { authority: { sourceTreeSha256: treeHash }, sourceFiles: [{ path: 'a', sourcePath: 'a.cc', sha256: sourceHash }], units: [{ id: 'op:a', coverageStatus: 'VERIFIED', coverage: binding }] }; const historical = { references: [], driftedArtifacts: 183 }; const observed = new Map([['a', sourceHash], ['manifest', proofHash], ['production', proofHash]]); return { catalog, inventory, historical, observed, run() { return coverageBaseline(this.catalog, this.inventory, this.historical, file => this.observed.get(file) ?? null); } }; } test('matching receipts and source scope yield current coverage with stable identity', () => { const f = fixture(), first = f.run(); assert.equal(first.unitCount, 1); assert.equal(first.verifiedUnits, 1); assert.equal(first.history.oldDriftedArtifacts, 183); assert.equal(first.integrity.driftedArtifacts, 0); assert.deepEqual(f.run(), first); }); test('changed and missing receipt files never inherit a historical pass', () => { const f = fixture(); f.observed.set('production', digest('changed')); assert.equal(f.run().verifiedUnits, 0); assert.equal(f.run().integrity.driftedArtifacts, 1); f.observed.delete('production'); assert.equal(f.run().verifiedUnits, 0); assert.equal(f.run().integrity.missingArtifacts, 1); }); test('matching receipt bytes do not prove behavior on changed source', () => { const f = fixture(); f.observed.set('a', digest('new source')); const result = f.run(); assert.equal(result.history.referenceValidUnits, 1); assert.equal(result.verifiedUnits, 0); assert.equal(result.source.changedFiles, 1); assert.ok(result.evidence[0].reasons.includes('SOURCE_VERSION_UNBOUND')); }); test('all unmatched units remain in the shared denominator', () => { const f = fixture(); f.catalog.entries.push({ id: 'route-only' }); f.inventory.units.push({ id: 'inventory-only' }); const result = f.run(); assert.equal(result.unitCount, 3); assert.equal(result.unverifiedUnits, 2); assert.deepEqual(result.reconciliation.catalogOnly, ['route-only']); assert.deepEqual(result.reconciliation.inventoryOnly, ['inventory-only']); }); test('malformed IDs, duplicate IDs and inconsistent inventory identity fail closed', () => { const f = fixture(); f.catalog.entries.push({ id: 'op:a' }); assert.throws(() => f.run(), /duplicate/); f.catalog.entries.pop(); f.catalog.entries[0].id = 42; assert.throws(() => f.run(), /string/); f.catalog.entries[0].id = 'op:a'; f.inventory.authority.sourceTreeSha256 = digest('wrong inventory'); const result = f.run(); assert.equal(result.verifiedUnits, 0); assert.ok(result.evidence[0].reasons.includes('INVENTORY_SNAPSHOT_INVALID')); }); test('case facts require real numeric exit/test counts and preserve remaining gates', () => { const r = receipt(), valid = caseEvidence(r, () => proofHash); assert.equal(valid.cases[0].currentSelectedTests, 2); assert.equal(valid.acceptance, 'NOT_CLAIMED'); assert.deepEqual(valid.remainingGates, ['production']); r.cases[0].process.code = '0'; assert.equal(caseEvidence(r, () => proofHash).cases[0].currentSelectedTests, 0); r.cases[0].process.code = 0; r.cases[0].result.tests = '2'; assert.equal(caseEvidence(r, () => proofHash).cases[0].currentSelectedTests, 0); }); test('case input changes, missing artifacts and unknown hash types invalidate reuse', () => { const r = receipt(); assert.equal(caseEvidence(r, file => file === 'input' ? digest('changed') : proofHash).cases[0].eligible, false); assert.equal(caseEvidence(r, () => null).cases[0].eligible, false); assert.throws(() => caseEvidence(r, () => 123)); r.cases[0].artifacts = []; assert.equal(caseEvidence(r, () => proofHash).cases[0].eligible, false); });