perf(web): measure and reuse batch verification stages
This commit is contained in:
@@ -24,10 +24,11 @@ function waitMs(milliseconds) {
|
||||
}
|
||||
|
||||
function command(command, logPath) {
|
||||
const started = Date.now();
|
||||
const result = spawnSync("bash", ["-lc", command], { cwd: root, encoding: "utf8", maxBuffer: 16 * 1024 * 1024 });
|
||||
const output = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
||||
if (logPath) fs.writeFileSync(abs(logPath), output);
|
||||
return { code: result.status ?? 1, output };
|
||||
return { code: result.status ?? 1, durationMs: Date.now() - started, output };
|
||||
}
|
||||
|
||||
function currentTask() {
|
||||
@@ -62,6 +63,20 @@ function assertContext() {
|
||||
if (result.code !== 0) throw new Error(`context gate failed (exit ${result.code})`);
|
||||
}
|
||||
|
||||
function typecheckProven(task) {
|
||||
try {
|
||||
const manifest = JSON.parse(read(`tests/golden/${task}/manifest.json`));
|
||||
const receiptPath = manifest.artifacts?.moduleReceipt?.path;
|
||||
if (!receiptPath) return false;
|
||||
const receipt = JSON.parse(read(receiptPath));
|
||||
return receipt.status === "PASS" && receipt.source?.unchanged === true
|
||||
&& receipt.commands?.some((entry) => entry.exitCode === 0 && entry.command.trim() === "npm --prefix web run typecheck");
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let iterations = 0;
|
||||
const summary = [];
|
||||
while (maxIterations === 0 || iterations < maxIterations) {
|
||||
@@ -82,7 +97,10 @@ while (maxIterations === 0 || iterations < maxIterations) {
|
||||
const after = currentTask();
|
||||
const terminal = after.task === before.task && terminalTask(before.task);
|
||||
if (after.task === before.task && !terminal) throw new Error(`${before.task} focused command exited 0 without advancing queue; log=${logPath}`);
|
||||
const gates = command("node tools/web/check-context-governance.mjs && node tools/web/check-execution-control-plane.mjs --allow-unrunnable && node tools/web/check-v2-task-index.mjs && node tools/web/check-v2-handoff.mjs && npm --prefix web run typecheck && npm --prefix web run lint && git diff --check", `tests/golden/${before.task}/continuous-gates.log`);
|
||||
const typecheckCommand = typecheckProven(before.task)
|
||||
? "printf 'typecheck reused from hash-bound module receipt\\n'"
|
||||
: "npm --prefix web run typecheck";
|
||||
const gates = command(`node tools/web/check-context-governance.mjs && node tools/web/check-execution-control-plane.mjs --allow-unrunnable && node tools/web/check-v2-task-index.mjs && node tools/web/check-v2-handoff.mjs && ${typecheckCommand} && npm --prefix web run lint && git diff --check`, `tests/golden/${before.task}/continuous-gates.log`);
|
||||
if (gates.code !== 0) throw new Error(`${before.task} post-handoff gate failed (exit ${gates.code}); log=tests/golden/${before.task}/continuous-gates.log`);
|
||||
iterations += 1;
|
||||
summary.push({ task: before.task, command: focused, nextTask: terminal ? null : after.task, terminal, log: logPath });
|
||||
|
||||
@@ -108,13 +108,14 @@ const reusableProductionEvidence = () => {
|
||||
const reusedEvidence = reusableProductionEvidence();
|
||||
if (reusedEvidence) {
|
||||
for (const command of record.module.commands ?? []) {
|
||||
results.push({ command, exitCode: 0, reused: true, output: `reused existing Chromium production evidence: ${reusedEvidence.evidencePath}\n` });
|
||||
results.push({ command, exitCode: 0, reused: true, durationMs: 0, output: `reused existing Chromium production evidence: ${reusedEvidence.evidencePath}\n` });
|
||||
}
|
||||
} else {
|
||||
for (const command of record.module.commands ?? []) {
|
||||
const started = Date.now();
|
||||
const result = spawnSync("bash", ["-lc", command], { cwd: root, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
|
||||
const output = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
||||
results.push({ command, exitCode: result.status ?? 1, output });
|
||||
results.push({ command, exitCode: result.status ?? 1, durationMs: Date.now() - started, output });
|
||||
if ((result.status ?? 1) !== 0) { failed = true; break; }
|
||||
}
|
||||
}
|
||||
@@ -131,9 +132,9 @@ const report = {
|
||||
source: { paths: record.module.sourcePaths, before: sourceBefore, after: sourceAfter, unchanged: sourceUnchanged },
|
||||
reusedReceipts,
|
||||
cases: { positive: record.module.positive, negative: record.module.negative, recovery: record.module.recovery },
|
||||
commands: results.map(({ command, exitCode }) => ({ command, exitCode })),
|
||||
commands: results.map(({ command, exitCode, durationMs, reused }) => ({ command, exitCode, durationMs, ...(reused ? { reused: true } : {}) })),
|
||||
verification: { required: plan.verificationPolicy.required, chromiumOnly: plan.verificationPolicy.browser === "chromium_only", fullFamilyParity: false },
|
||||
efficiency: { existingEvidenceReused: Boolean(reusedEvidence), skippedCommands: reusedEvidence ? results.length : 0, reusePolicy: reuseRequested ? "hash_bound_receipt" : "disabled" },
|
||||
efficiency: { existingEvidenceReused: Boolean(reusedEvidence), skippedCommands: reusedEvidence ? results.length : 0, totalDurationMs: results.reduce((total, result) => total + (result.durationMs ?? 0), 0), reusePolicy: reuseRequested ? "hash_bound_receipt" : "disabled" },
|
||||
inventory: { historical: plan.inventory, dynamic: { path: dynamicInventoryPath, sha256: sha(dynamicInventoryPath), sourceTreeSha256: dynamicInventory.authority.sourceTreeSha256, unitCount: dynamicInventory.summary.unitCount, planningEstimate: dynamicInventory.policy.planningEstimate, hardTarget: dynamicInventory.policy.hardTarget, verifiedUnits: dynamicInventory.coverage.verifiedUnits, unverifiedUnits: dynamicInventory.coverage.unverifiedUnits } },
|
||||
nextTask: failed || !sourceUnchanged ? task : plan.tasks[plan.tasks.findIndex((candidate) => candidate.id === task) + 1]?.id ?? null,
|
||||
};
|
||||
|
||||
@@ -30,6 +30,7 @@ for (const source of taskRecord?.module?.sourcePaths ?? []) {
|
||||
}
|
||||
const runtimeAllowlist = new Set([
|
||||
"tools/web/run-wbv2-module-task.mjs",
|
||||
"tools/web/run-wbv2-continuous.mjs",
|
||||
"tools/web/bind-wbv2-module-coverage.mjs",
|
||||
"tools/web/finalize-wbv2-module-batch.mjs",
|
||||
"tools/web/check-source-dynamic-inventory.mjs",
|
||||
|
||||
Reference in New Issue
Block a user