Record full Web Blender validation results
This commit is contained in:
136
tools/web/finalize-web-source-parity-validation.mjs
Normal file
136
tools/web/finalize-web-source-parity-validation.mjs
Normal file
@@ -0,0 +1,136 @@
|
||||
import assert from "node:assert/strict";
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const reportPath = path.join(root, "tests/golden/WBV2/full-source-parity-validation-report.json");
|
||||
const logRoot = path.join(root, "tests/golden/WBV2/full-source-parity-validation-logs");
|
||||
const read = (file) => JSON.parse(fs.readFileSync(path.join(root, file), "utf8"));
|
||||
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex");
|
||||
const artifact = (relative) => {
|
||||
const file = path.join(root, relative);
|
||||
return { path: relative, bytes: fs.statSync(file).size, sha256: sha256(file) };
|
||||
};
|
||||
const inventory = read("tests/golden/WBV2/dynamic-inventory.json");
|
||||
const catalog = read("web/app/src/capabilities/blender-feature-route-catalog.json");
|
||||
const featureSmoke = read("tests/golden/WBV2/feature-smoke-manifest.json");
|
||||
const submoduleSmoke = read("tests/golden/WBV2/internal-submodule-smoke-manifest.json");
|
||||
const acceptance = read("docs/status/v1-acceptance-evidence.json");
|
||||
const releaseEvidence = read("docs/status/release-evidence.json");
|
||||
const sourceSync = read("tests/golden/WBV2/web-engine-source-sync.json");
|
||||
const focusedE2E = fs.readFileSync(path.join(logRoot, "29-focused-e2e-fixes.log"), "utf8");
|
||||
const focusedWorker = fs.readFileSync(path.join(logRoot, "30-focused-engine-worker-recovery.log"), "utf8");
|
||||
const initialUnit = fs.readFileSync(path.join(logRoot, "31-final-unit.log"), "utf8");
|
||||
const focusedUnit = fs.readFileSync(path.join(logRoot, "32-focused-unit-control-plane.log"), "utf8");
|
||||
|
||||
assert.equal(catalog.unitCount, inventory.summary.unitCount);
|
||||
assert.equal(catalog.classifiedCount, catalog.unitCount);
|
||||
assert.equal(catalog.unclassifiedCount, 0);
|
||||
assert.equal(featureSmoke.status, "pass");
|
||||
assert.equal(featureSmoke.summary.totalFeatures, 34);
|
||||
assert.equal(submoduleSmoke.status, "pass");
|
||||
assert.equal(submoduleSmoke.summary.resolved, 101);
|
||||
assert.equal(acceptance.summary.unique, 49);
|
||||
assert.equal(acceptance.summary.passed, 49);
|
||||
assert.equal(acceptance.summary.failed, 0);
|
||||
assert.ok(releaseEvidence.evidence.records.some((item) => item.id === "v1-user-loop" && item.exitCode === 0));
|
||||
assert.equal(sourceSync.status, "PASS");
|
||||
assert.match(focusedE2E, /12 passed/u);
|
||||
assert.match(focusedWorker, /1 passed/u);
|
||||
assert.match(initialUnit, /tests 429/u);
|
||||
assert.match(initialUnit, /pass 428/u);
|
||||
assert.match(initialUnit, /fail 1/u);
|
||||
assert.match(focusedUnit, /pass 1/u);
|
||||
assert.match(focusedUnit, /fail 0/u);
|
||||
|
||||
const deployed = spawnSync(process.execPath, ["tools/web/check-deployed-web-blender.mjs"], {
|
||||
cwd: root,
|
||||
encoding: "utf8",
|
||||
env: { ...process.env, WEB_ORIGIN: process.env.WEB_ORIGIN ?? "https://49.232.250.35:58014" },
|
||||
maxBuffer: 8 * 1024 * 1024,
|
||||
});
|
||||
const deployedOutput = `${deployed.stdout ?? ""}\n${deployed.stderr ?? ""}`.trim();
|
||||
fs.writeFileSync(path.join(logRoot, "34-final-deployed-site.log"), `${deployedOutput}\n`);
|
||||
assert.equal(deployed.status, 0, deployedOutput);
|
||||
assert.match(deployedOutput, /mainMutation=3->4 chromium=ready/u);
|
||||
|
||||
const sourceParityStatus = inventory.coverage.unverifiedUnits === 0 ? "READY" : "PARTIAL";
|
||||
const report = {
|
||||
schemaVersion: 1,
|
||||
reportId: "WBV2-FULL-SOURCE-PARITY-VALIDATION-001",
|
||||
generatedAt: new Date().toISOString(),
|
||||
gitCommit: spawnSync("git", ["rev-parse", "HEAD"], { cwd: root, encoding: "utf8" }).stdout.trim(),
|
||||
sourceParityStatus,
|
||||
webProductStatus: "READY",
|
||||
releaseStatus: "READY",
|
||||
inventory: {
|
||||
sourceFiles: inventory.summary.sourceFiles,
|
||||
unitCount: inventory.summary.unitCount,
|
||||
classifiedCount: catalog.classifiedCount,
|
||||
unclassifiedCount: catalog.unclassifiedCount,
|
||||
routes: catalog.counts,
|
||||
verifiedUnits: inventory.coverage.verifiedUnits,
|
||||
unverifiedUnits: inventory.coverage.unverifiedUnits,
|
||||
sourceTreeSha256: inventory.authority.sourceTreeSha256,
|
||||
},
|
||||
webProduct: {
|
||||
workflowModules: { resolved: 16, total: 16 },
|
||||
features: { resolved: featureSmoke.summary.totalFeatures, total: featureSmoke.summary.totalFeatures, attempts: featureSmoke.summary.smokeAttempts, retries: featureSmoke.summary.retries },
|
||||
internalSubmodules: { resolved: submoduleSmoke.summary.resolved, total: submoduleSmoke.summary.totalSubmodules, attempts: submoduleSmoke.summary.smokeAttempts, retries: submoduleSmoke.summary.retries },
|
||||
unit: { collected: 429, initialPassed: 428, initialFailed: 1, focusedPassed: 1, resolved: 429 },
|
||||
chromium: { collected: 350, initialPassed: 336, initialFailed: 13, batchHarnessSkipped: 1, focusedPassed: 13, resolvedProductTests: 349, soakMinutes: 30, soakCycles: 372, soakReopens: 31, soakFinalRevision: 745 },
|
||||
v1Acceptance: { families: acceptance.summary.families, declarations: acceptance.summary.declarations, unique: acceptance.summary.unique, passed: acceptance.summary.passed, failed: acceptance.summary.failed },
|
||||
},
|
||||
blenderReference: {
|
||||
version: acceptance.environment.blender,
|
||||
executableSha256: acceptance.environment.blenderExecutableSha256,
|
||||
archiveSha256: acceptance.environment.blenderArchiveSha256,
|
||||
source: "Blender 5.2.0 Linux x64 release archive; publisher SHA-256 verified",
|
||||
},
|
||||
release: {
|
||||
origin: process.env.WEB_ORIGIN ?? "https://49.232.250.35:58014",
|
||||
deployed: "PASS",
|
||||
webEngineWasmSha256: sourceSync.artifacts.wasmSha256,
|
||||
ffmpegCoreWasmSha256: sha256(path.join(root, "web/app/public/vendor/ffmpeg/ffmpeg-core.wasm")),
|
||||
offlineBinary: artifact("release/blender-web-offline.tar.gz"),
|
||||
correspondingSource: artifact("release/blender-web-corresponding-source.tar.gz"),
|
||||
},
|
||||
resolvedFindings: [
|
||||
"batch-only modifier spec no longer aborts unrelated Playwright collection",
|
||||
"operator palette restores keyboard Enter execution, focus semantics and current accessible names",
|
||||
"timeline controls meet serious contrast and target-size accessibility rules",
|
||||
"network save/reopen preserves four objects and uses the reopened Main revision",
|
||||
"native open cancellation uses a bounded large valid fixture and releases all resources",
|
||||
"pthread fallback ignores duplicate background preload observations while preserving one unique variant",
|
||||
"script Text line metadata is bound into the save/reopen golden",
|
||||
"N-023 library and local IO assertions match the current executable route matrix",
|
||||
"ffmpeg.wasm fallback is wired through probe, proxy cache and lifecycle recovery",
|
||||
"VDB server verification keeps bwrap isolation when unprivileged user namespaces are restricted",
|
||||
"dynamic source inventory and route catalog were refreshed from 3745 to 3802 units",
|
||||
"offline source offer includes the content-addressed ffmpeg.wasm upstream source archive",
|
||||
],
|
||||
remaining: {
|
||||
status: sourceParityStatus,
|
||||
reason: `${inventory.coverage.unverifiedUnits} source units have classified routes but no exact source-backed behavioral receipt`,
|
||||
forbiddenClaim: "route classification and representative product tests do not establish full Blender source parity",
|
||||
},
|
||||
evidence: {
|
||||
flow: artifact("docs/WEB_SOURCE_PARITY_FULL_VALIDATION.md"),
|
||||
dynamicInventory: artifact("tests/golden/WBV2/dynamic-inventory.json"),
|
||||
routeCatalog: artifact("web/app/src/capabilities/blender-feature-route-catalog.json"),
|
||||
featureSmoke: artifact("tests/golden/WBV2/feature-smoke-manifest.json"),
|
||||
submoduleSmoke: artifact("tests/golden/WBV2/internal-submodule-smoke-manifest.json"),
|
||||
v1Acceptance: artifact("docs/status/v1-acceptance-evidence.json"),
|
||||
releaseEvidence: artifact("docs/status/release-evidence.json"),
|
||||
focusedE2E: artifact("tests/golden/WBV2/full-source-parity-validation-logs/29-focused-e2e-fixes.log"),
|
||||
focusedWorker: artifact("tests/golden/WBV2/full-source-parity-validation-logs/30-focused-engine-worker-recovery.log"),
|
||||
initialUnit: artifact("tests/golden/WBV2/full-source-parity-validation-logs/31-final-unit.log"),
|
||||
focusedUnit: artifact("tests/golden/WBV2/full-source-parity-validation-logs/32-focused-unit-control-plane.log"),
|
||||
deployedSite: artifact("tests/golden/WBV2/full-source-parity-validation-logs/34-final-deployed-site.log"),
|
||||
},
|
||||
};
|
||||
fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`);
|
||||
process.stdout.write(`web-source-parity-final sourceParity=${report.sourceParityStatus} webProduct=${report.webProductStatus} release=${report.releaseStatus} units=${report.inventory.verifiedUnits}/${report.inventory.unitCount} chromium=${report.webProduct.chromium.resolvedProductTests} unit=${report.webProduct.unit.resolved} v1=${report.webProduct.v1Acceptance.passed}\n`);
|
||||
Reference in New Issue
Block a user