feat(web): reuse verified source dependencies
This commit is contained in:
@@ -16,15 +16,13 @@ const arg = (name, fallback = null) => {
|
||||
const task = arg("--task");
|
||||
if (!task) throw new Error("usage: node tools/web/bind-wbv2-module-coverage.mjs --task <task-id>");
|
||||
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 productionPath = arg("--production", module?.evidencePaths?.[0] ?? `tests/golden/${task}/modifier-reader-batch-production.json`);
|
||||
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);
|
||||
@@ -35,21 +33,38 @@ assert.equal(production.queueMutation, false);
|
||||
const inventoryPath = "tests/golden/WBV2/dynamic-inventory.json";
|
||||
const inventory = json(inventoryPath);
|
||||
const fixturePaths = Array.isArray(production.fixtures) ? production.fixtures : production.fixture ? [production.fixture] : [];
|
||||
assert.ok(fixturePaths.length, "production evidence has no fixture(s)");
|
||||
const fixtureEvidence = Array.isArray(production.fixtures)
|
||||
? fixturePaths.map((fixture) => production[fixture])
|
||||
: [production];
|
||||
for (const evidence of fixtureEvidence) {
|
||||
assert.ok(evidence && typeof evidence === "object", "fixture result is missing");
|
||||
assert.equal(evidence.error, undefined);
|
||||
assert.equal(evidence.saveReopenExact, true);
|
||||
assert.equal(evidence.deterministicExact, true);
|
||||
}
|
||||
if (Array.isArray(production.fixtures)) {
|
||||
assert.equal(typeof production.fixtureSha256, "object");
|
||||
for (const fixture of fixturePaths) assert.equal(production.fixtureSha256[fixture], sha(fixture), `fixture hash drift: ${fixture}`);
|
||||
const validateEvidence = (evidencePath) => {
|
||||
const evidence = json(evidencePath);
|
||||
assert.equal(evidence.browser, "chromium");
|
||||
assert.equal(evidence.queueMutation, false);
|
||||
const paths = Array.isArray(evidence.fixtures) ? evidence.fixtures : evidence.fixture ? [evidence.fixture] : [];
|
||||
assert.ok(paths.length, `production evidence has no fixture(s): ${evidencePath}`);
|
||||
const entries = Array.isArray(evidence.fixtures) ? paths.map((fixture) => evidence[fixture]) : [evidence];
|
||||
for (const entry of entries) {
|
||||
assert.ok(entry && typeof entry === "object", "fixture result is missing");
|
||||
assert.equal(entry.error, undefined);
|
||||
if (entry.saveReopenExact !== undefined) assert.equal(entry.saveReopenExact, true);
|
||||
if (entry.deterministicExact !== undefined) assert.equal(entry.deterministicExact, true);
|
||||
if (entry.exact !== undefined) assert.equal(entry.exact, true);
|
||||
}
|
||||
if (Array.isArray(evidence.fixtures)) {
|
||||
assert.equal(typeof evidence.fixtureSha256, "object");
|
||||
for (const fixture of paths) assert.equal(evidence.fixtureSha256[fixture], sha(fixture), `fixture hash drift: ${fixture}`);
|
||||
} else {
|
||||
assert.equal(evidence.fixtureSha256, sha(evidence.fixture));
|
||||
}
|
||||
return evidence;
|
||||
};
|
||||
if (production.reusedEvidence?.length) {
|
||||
assert.ok(production.dependencyProofs?.length, "dependency reuse evidence has no proofs");
|
||||
for (const evidence of production.reusedEvidence) {
|
||||
assert.ok(evidence.path, "reused evidence path is missing");
|
||||
validateEvidence(evidence.path);
|
||||
assert.equal(evidence.sha256, sha(evidence.path), `reused evidence hash drift: ${evidence.path}`);
|
||||
}
|
||||
} else {
|
||||
assert.equal(production.fixtureSha256, sha(production.fixture));
|
||||
assert.ok(fixturePaths.length, "production evidence has no fixture(s)");
|
||||
validateEvidence(productionPath);
|
||||
}
|
||||
const bindingsPath = "tests/golden/WBV2/dynamic-coverage-bindings.json";
|
||||
const existing = fs.existsSync(abs(bindingsPath)) ? json(bindingsPath) : [];
|
||||
|
||||
95
tools/web/reuse-wbv2-source-dependencies.mjs
Normal file
95
tools/web/reuse-wbv2-source-dependencies.mjs
Normal file
@@ -0,0 +1,95 @@
|
||||
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) => {
|
||||
const index = process.argv.indexOf(name);
|
||||
return index >= 0 ? process.argv[index + 1] : null;
|
||||
};
|
||||
const task = arg("--task");
|
||||
if (!task || !process.argv.includes("--write")) throw new Error("usage: node tools/web/reuse-wbv2-source-dependencies.mjs --task <task-id> --write");
|
||||
|
||||
const inventoryPath = "tests/golden/WBV2/dynamic-inventory.json";
|
||||
const inventory = json(inventoryPath);
|
||||
const index = json("tests/golden/WBV2/task-index.json");
|
||||
const plan = json(index.source.path);
|
||||
const record = plan.tasks.find((candidate) => candidate.id === task);
|
||||
const module = record?.module;
|
||||
assert.ok(module?.dependencyReuse?.length, `task ${task} has no dependency reuse map`);
|
||||
const bindings = json("tests/golden/WBV2/dynamic-coverage-bindings.json");
|
||||
const bindingByUnit = new Map(bindings.filter((binding) => binding.status === "VERIFIED").map((binding) => [binding.unitId, binding]));
|
||||
|
||||
function validateEvidence(evidencePath) {
|
||||
const evidence = json(evidencePath);
|
||||
assert.equal(evidence.browser, "chromium", `evidence is not Chromium: ${evidencePath}`);
|
||||
assert.equal(evidence.queueMutation, false, `evidence mutated queue: ${evidencePath}`);
|
||||
const fixturePaths = Array.isArray(evidence.fixtures) ? evidence.fixtures : evidence.fixture ? [evidence.fixture] : [];
|
||||
assert.ok(fixturePaths.length, `evidence has no fixture(s): ${evidencePath}`);
|
||||
const entries = Array.isArray(evidence.fixtures) ? fixturePaths.map((fixture) => evidence[fixture]) : [evidence];
|
||||
for (const entry of entries) {
|
||||
assert.ok(entry && entry.error === undefined, `evidence fixture failed: ${evidencePath}`);
|
||||
if (entry.saveReopenExact !== undefined) assert.equal(entry.saveReopenExact, true);
|
||||
if (entry.deterministicExact !== undefined) assert.equal(entry.deterministicExact, true);
|
||||
if (entry.exact !== undefined) assert.equal(entry.exact, true);
|
||||
}
|
||||
if (Array.isArray(evidence.fixtures)) {
|
||||
for (const fixture of fixturePaths) assert.equal(evidence.fixtureSha256?.[fixture], sha(fixture), `fixture hash drift: ${fixture}`);
|
||||
} else {
|
||||
assert.equal(evidence.fixtureSha256, sha(evidence.fixture), `fixture hash drift: ${evidence.fixture}`);
|
||||
}
|
||||
return { path: evidencePath, sha256: sha(evidencePath), fixtures: fixturePaths };
|
||||
}
|
||||
|
||||
const proofs = [];
|
||||
const reusedEvidence = new Map();
|
||||
for (const dependency of module.dependencyReuse) {
|
||||
const unit = inventory.units.find((candidate) => candidate.id === dependency.unitId);
|
||||
assert.ok(unit, `dynamic unit missing: ${dependency.unitId}`);
|
||||
assert.equal(unit.coverageStatus, "UNVERIFIED", `dependency unit is already verified: ${dependency.unitId}`);
|
||||
const representative = bindingByUnit.get(dependency.representativeUnitId);
|
||||
assert.ok(representative, `verified representative binding missing: ${dependency.representativeUnitId}`);
|
||||
assert.equal(representative.sourceTreeSha256, inventory.authority.sourceTreeSha256);
|
||||
assert.ok(fs.existsSync(abs(dependency.proofSource)), `dependency proof source missing: ${dependency.proofSource}`);
|
||||
const proofText = read(dependency.proofSource);
|
||||
assert.ok(proofText.includes(dependency.marker), `dependency marker missing: ${dependency.marker}`);
|
||||
assert.ok(fs.existsSync(abs(unit.locations?.[0]?.path)), `dependency source missing: ${unit.locations?.[0]?.path}`);
|
||||
assert.ok(read(unit.locations[0].path).includes(dependency.marker), `dependency source marker missing: ${dependency.marker}`);
|
||||
const evidence = validateEvidence(dependency.productionEvidence);
|
||||
reusedEvidence.set(evidence.path, evidence);
|
||||
proofs.push({
|
||||
unitId: dependency.unitId,
|
||||
sourceLocation: unit.locations?.[0],
|
||||
representativeUnitId: dependency.representativeUnitId,
|
||||
representativeBinding: { task: representative.task, productionEvidence: representative.productionEvidence },
|
||||
proofSource: dependency.proofSource,
|
||||
proofSourceSha256: sha(dependency.proofSource),
|
||||
marker: dependency.marker,
|
||||
productionEvidence: evidence,
|
||||
sourceTreeSha256: inventory.authority.sourceTreeSha256,
|
||||
});
|
||||
}
|
||||
|
||||
const reportPath = module.evidencePaths?.[0] ?? `tests/golden/${task}/source-dependency-reuse-production.json`;
|
||||
const report = {
|
||||
schemaVersion: 1,
|
||||
task,
|
||||
operation: "SOURCE_DEPENDENCY_REUSE_CHROMIUM_RECEIPT",
|
||||
status: "PASS",
|
||||
browser: "chromium",
|
||||
queueMutation: false,
|
||||
sourceUnits: module.coverageBindings,
|
||||
sourceTreeSha256: inventory.authority.sourceTreeSha256,
|
||||
dependencyProofs: proofs,
|
||||
reusedEvidence: [...reusedEvidence.values()],
|
||||
efficiency: { existingChromiumReceiptsReused: reusedEvidence.size, browserRuns: 0, buildRuns: 0, policy: "verified-downstream-receipt-plus-source-dependency" },
|
||||
};
|
||||
fs.mkdirSync(path.dirname(abs(reportPath)), { recursive: true });
|
||||
fs.writeFileSync(abs(reportPath), `${JSON.stringify(report, null, 2)}\n`);
|
||||
process.stdout.write(`wbv2-source-dependency-reuse-ok task=${task} units=${proofs.length} receipts=${reusedEvidence.size} browserRuns=0\n`);
|
||||
@@ -63,6 +63,30 @@ const reusableProductionEvidence = () => {
|
||||
catch { return null; }
|
||||
if (evidence.task !== task || evidence.browser !== "chromium" || evidence.queueMutation !== false
|
||||
|| evidence.error !== undefined) return null;
|
||||
if (evidence.reusedEvidence?.length && evidence.dependencyProofs?.length) {
|
||||
for (const reused of evidence.reusedEvidence) {
|
||||
if (!reused.path || !fs.existsSync(abs(reused.path))) return null;
|
||||
let prior;
|
||||
try { prior = json(reused.path); }
|
||||
catch { return null; }
|
||||
const paths = Array.isArray(prior.fixtures) ? prior.fixtures : prior.fixture ? [prior.fixture] : [];
|
||||
const entries = Array.isArray(prior.fixtures) ? paths.map((fixture) => prior[fixture]) : [prior];
|
||||
if (!paths.length || entries.some((entry) => !entry || entry.error !== undefined
|
||||
|| (entry.saveReopenExact !== undefined && entry.saveReopenExact !== true)
|
||||
|| (entry.deterministicExact !== undefined && entry.deterministicExact !== true)
|
||||
|| (entry.exact !== undefined && entry.exact !== true))) return null;
|
||||
if (Array.isArray(prior.fixtures)) {
|
||||
if (paths.some((fixture) => !fs.existsSync(abs(fixture)) || prior.fixtureSha256?.[fixture] !== sha(fixture))) return null;
|
||||
} else if (!fs.existsSync(abs(prior.fixture)) || prior.fixtureSha256 !== sha(prior.fixture)) return null;
|
||||
}
|
||||
if (!fs.existsSync(abs(reportPath))) return null;
|
||||
let previousReceipt;
|
||||
try { previousReceipt = json(reportPath); }
|
||||
catch { return null; }
|
||||
if (previousReceipt.status !== "PASS" || previousReceipt.source?.unchanged !== true) return null;
|
||||
if (JSON.stringify(previousReceipt.source?.after ?? {}) !== JSON.stringify(sourceBefore)) return null;
|
||||
return { evidencePath, evidence };
|
||||
}
|
||||
const fixturePaths = Array.isArray(evidence.fixtures) ? evidence.fixtures : evidence.fixture ? [evidence.fixture] : [];
|
||||
if (!fixturePaths.length) return null;
|
||||
const fixtureEvidence = Array.isArray(evidence.fixtures) ? fixturePaths.map((fixture) => evidence[fixture]) : [evidence];
|
||||
|
||||
Reference in New Issue
Block a user