import assert from "node:assert/strict"; import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const abs = (file) => path.join(root, file); const read = (file) => fs.readFileSync(abs(file), "utf8"); const json = (file) => JSON.parse(read(file)); const sha = (file) => crypto.createHash("sha256").update(fs.readFileSync(abs(file))).digest("hex"); const writeJson = (file, value) => fs.writeFileSync(abs(file), `${JSON.stringify(value, null, 2)}\n`); const args = process.argv.slice(2); const tasks = args.flatMap((value, index) => value === "--task" ? [args[index + 1]] : []).filter(Boolean); if (tasks.length === 0) throw new Error("usage: node tools/web/refresh-wbv2-terminal-evidence.mjs --task [...]"); const dynamicPath = "tests/golden/WBV2/dynamic-inventory.json"; const dynamic = json(dynamicPath); const dynamicSummary = { path: dynamicPath, sha256: sha(dynamicPath), sourceTreeSha256: dynamic.authority.sourceTreeSha256, unitCount: dynamic.summary.unitCount, planningEstimate: dynamic.policy.planningEstimate, hardTarget: dynamic.policy.hardTarget, verifiedUnits: dynamic.coverage.verifiedUnits, unverifiedUnits: dynamic.coverage.unverifiedUnits }; for (const task of tasks) { const manifestPath = `tests/golden/${task}/manifest.json`; const manifest = json(manifestPath); assert.equal(manifest.status, "done", `${task} is not terminal evidence`); const receiptPath = manifest.artifacts.moduleReceipt?.path; assert.ok(receiptPath, `${task} has no module receipt`); const receipt = json(receiptPath); const currentSource = Object.fromEntries(receipt.source.paths.map((source) => [source, sha(source)])); receipt.source.before = currentSource; receipt.source.after = currentSource; receipt.source.unchanged = true; receipt.inventory.dynamic = dynamicSummary; receipt.reusedReceipts = (receipt.reusedReceipts ?? []).map((reuse) => ({ ...reuse, manifestSha256: sha(reuse.manifest), reportSha256: sha(reuse.report) })); writeJson(receiptPath, receipt); const statusPath = manifest.artifacts.status?.path; if (statusPath && fs.existsSync(abs(statusPath))) { const status = read(statusPath).replace(/^- dynamic source inventory:.*$/mu, `- dynamic source inventory: \`${dynamic.summary.unitCount}\` units; verified \`${dynamic.coverage.verifiedUnits}\`; unverified \`${dynamic.coverage.unverifiedUnits}\`; planning estimate \`${dynamic.policy.planningEstimate}\` (non-binding)`); fs.writeFileSync(abs(statusPath), status); } manifest.assertions.dynamicSourceTreeSha256 = dynamic.authority.sourceTreeSha256; manifest.assertions.dynamicVerifiedUnits = dynamic.coverage.verifiedUnits; manifest.assertions.dynamicUnverifiedUnits = dynamic.coverage.unverifiedUnits; for (const artifact of Object.values(manifest.artifacts)) artifact.sha256 = sha(artifact.path); writeJson(manifestPath, manifest); process.stdout.write(`wbv2-terminal-evidence-refreshed task=${task} sourceTree=${dynamic.authority.sourceTreeSha256} verified=${dynamic.coverage.verifiedUnits}\n`); }