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 arg = (name, fallback = null) => { const index = process.argv.indexOf(name); return index >= 0 ? process.argv[index + 1] : fallback; }; const task = arg("--task"); if (!task) throw new Error("usage: node tools/web/bind-wbv2-module-coverage.mjs --task "); const manifestPath = `tests/golden/${task}/manifest.json`; const productionPath = arg("--production", `tests/golden/${task}/modifier-reader-batch-production.json`); const manifest = json(manifestPath); assert.equal(manifest.status, "done"); const moduleRecord = Object.values(json("tests/golden/WBV2-P1100-000/module-execution-plan.json").tasks ?? {}) .find((candidate) => candidate.id === task); const planPath = manifest.artifacts.plan.path; const plan = json(planPath); const taskRecord = plan.tasks.find((candidate) => candidate.id === task); const module = taskRecord?.module; const requestedUnits = (arg("--units") ?? "").split(",").map((value) => value.trim()).filter(Boolean); const coverageBindings = requestedUnits.length > 0 ? requestedUnits : module?.coverageBindings ?? []; const capabilityId = module?.moduleId ?? arg("--capability", task); if (!coverageBindings.length) throw new Error(`task ${task} has no coverageBindings`); const production = json(productionPath); assert.equal(production.browser, "chromium"); assert.equal(production.queueMutation, false); assert.equal(production.error, undefined); assert.equal(production.saveReopenExact, true); assert.equal(production.deterministicExact, true); const inventoryPath = "tests/golden/WBV2/dynamic-inventory.json"; const inventory = json(inventoryPath); assert.equal(production.fixtureSha256, sha(production.fixture)); const bindingsPath = "tests/golden/WBV2/dynamic-coverage-bindings.json"; const existing = fs.existsSync(abs(bindingsPath)) ? json(bindingsPath) : []; const byId = new Map(existing.map((binding) => [binding.unitId, binding])); for (const unitId of coverageBindings) { const unit = inventory.units.find((candidate) => candidate.id === unitId); assert.ok(unit, `dynamic unit missing: ${unitId}`); if (unit.coverageStatus === "VERIFIED") { assert.equal(byId.get(unitId)?.task, task, `dynamic unit already belongs to another task: ${unitId}`); } const sourceLocation = unit.locations?.[0]; assert.ok(sourceLocation?.path, `source location missing: ${unitId}`); byId.set(unitId, { unitId, task, capabilityId, sourceLocation, evidenceManifest: { path: manifestPath, sha256: sha(manifestPath) }, productionEvidence: { path: productionPath, sha256: sha(productionPath) }, sourceTreeSha256: inventory.authority.sourceTreeSha256, status: "VERIFIED", }); } const bindings = [...byId.values()]; const verifiedIds = new Set(bindings.map((binding) => binding.unitId)); const updatedUnits = inventory.units.map((unit) => verifiedIds.has(unit.id) ? { ...unit, coverageStatus: "VERIFIED", coverage: bindings.find((binding) => binding.unitId === unit.id) } : { ...unit, coverageStatus: "UNVERIFIED", ...(unit.coverage ? {} : {}) }); const verifiedUnits = updatedUnits.filter((unit) => unit.coverageStatus === "VERIFIED").length; const updated = { ...inventory, coverage: { ...inventory.coverage, verifiedUnits, unverifiedUnits: inventory.summary.unitCount - verifiedUnits, sourceMappingRequired: inventory.summary.unitCount, inventoryMutation: "explicit_source_case_bindings_only", lastReconciledAt: "2026-09-01" }, units: updatedUnits, coverageLedger: bindings, }; fs.writeFileSync(abs(bindingsPath), `${JSON.stringify(bindings, null, 2)}\n`); fs.writeFileSync(abs(inventoryPath), `${JSON.stringify(updated, null, 2)}\n`); const coverageManifestPath = "tests/golden/WBV2/dynamic-coverage-manifest.json"; if (fs.existsSync(abs(coverageManifestPath))) { const coverageManifest = json(coverageManifestPath); coverageManifest.artifacts.inventory.sha256 = sha(inventoryPath); coverageManifest.artifacts.bindings.sha256 = sha(bindingsPath); coverageManifest.coverage = { ...coverageManifest.coverage, unitCount: inventory.summary.unitCount, verifiedUnits, unverifiedUnits: inventory.summary.unitCount - verifiedUnits, boundUnitDelta: coverageBindings.length, sourceTreeSha256: inventory.authority.sourceTreeSha256 }; fs.writeFileSync(abs(coverageManifestPath), `${JSON.stringify(coverageManifest, null, 2)}\n`); } const inventoryManifestPath = "tests/golden/WBV2/dynamic-inventory-manifest.json"; if (fs.existsSync(abs(inventoryManifestPath))) { const inventoryManifest = json(inventoryManifestPath); if (inventoryManifest.artifacts?.inventory) inventoryManifest.artifacts.inventory.sha256 = sha(inventoryPath); if (inventoryManifest.inventory) { inventoryManifest.inventory.verifiedUnits = verifiedUnits; inventoryManifest.inventory.unverifiedUnits = inventory.summary.unitCount - verifiedUnits; inventoryManifest.inventory.boundCaseDelta = coverageBindings.length; } fs.writeFileSync(abs(inventoryManifestPath), `${JSON.stringify(inventoryManifest, null, 2)}\n`); } const auditPath = "tests/golden/WBV2/dynamic-coverage-audit.json"; if (fs.existsSync(abs(auditPath))) { const audit = json(auditPath); const coverageByKind = {}; const coverageByFamily = {}; for (const unit of updatedUnits) { const kind = coverageByKind[unit.kind] ??= { verified: 0, unverified: 0 }; const family = coverageByFamily[unit.family] ??= { verified: 0, unverified: 0 }; const key = unit.coverageStatus === "VERIFIED" ? "verified" : "unverified"; kind[key] += 1; family[key] += 1; } audit.dynamicInventory = { ...(audit.dynamicInventory ?? {}), path: inventoryPath, afterSha256: sha(inventoryPath), unitCount: inventory.summary.unitCount, verifiedUnits, unverifiedUnits: inventory.summary.unitCount - verifiedUnits }; audit.explicitBindings = bindings; audit.coverageByKind = coverageByKind; audit.coverageByFamily = coverageByFamily; fs.writeFileSync(abs(auditPath), `${JSON.stringify(audit, null, 2)}\n`); } process.stdout.write(`wbv2-module-coverage-bound task=${task} module=${capabilityId} added=${coverageBindings.length} verified=${verifiedUnits} unverified=${inventory.summary.unitCount - verifiedUnits}\n`);