Files
workinf_Blender_Wasm/tools/web/finalize-web-source-parity-validation.mjs
mes123456 72bf0f47ad
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
Record full Web Blender validation results
2026-09-07 17:12:09 +08:00

137 lines
8.5 KiB
JavaScript

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`);