Files
workinf_Blender_Wasm/tools/web/check-lighting-field-parity.mjs
mes123456 0fe8d2bb56
Some checks are pending
M6 deployable RC / quick (push) Waiting to run
M6 deployable RC / chromium (push) Blocked by required conditions
M6 deployable RC / release (push) Blocked by required conditions
Advance M8-M11 parity workflows
2026-08-17 04:37:07 -04:00

79 lines
4.0 KiB
JavaScript

import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import ts from "../../web/node_modules/typescript/lib/typescript.js";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
const sourcePath = path.join(root, "web/protocol/scene-ir.ts");
const source = ts.createSourceFile(sourcePath, fs.readFileSync(sourcePath, "utf8"), ts.ScriptTarget.Latest, true);
const manifest = JSON.parse(fs.readFileSync(path.join(root, "tests/golden/M11-01/lighting-field-parity.json"), "utf8"));
function interfaceDeclaration(name) {
const declaration = source.statements.find((statement) => ts.isInterfaceDeclaration(statement) && statement.name.text === name);
assert.ok(declaration, `missing interface ${name}`);
return declaration;
}
function leafTypePaths(type, prefix) {
if (!ts.isTypeLiteralNode(type)) return [prefix];
return type.members.filter(ts.isPropertySignature).flatMap((member) =>
leafTypePaths(member.type, `${prefix}.${member.name.getText(source)}`));
}
function interfaceLeaves(name, include = () => true) {
return interfaceDeclaration(name).members.filter((member) =>
ts.isPropertySignature(member) && include(member.name.getText(source))).flatMap((member) =>
leafTypePaths(member.type, member.name.getText(source))).sort();
}
const expected = new Map([
["CAMERA", interfaceLeaves("CameraIR")],
["LIGHT", interfaceLeaves("LightIR")],
["WORLD", interfaceLeaves("WorldIR")],
["SCENE_COLOR_MANAGEMENT", interfaceLeaves("SceneIR", (name) => name === "renderEngine" || name === "colorManagement")],
]);
const stages = ["reader", "writer", "viewportMain", "viewportOffscreen"];
const stageStates = new Set(["VERIFIED", "PARTIAL", "METADATA_ONLY", "BLOCKED", "NOT_APPLICABLE"]);
const parityStates = new Set(["COMPLETE", "PARTIAL", "BLOCKED"]);
assert.equal(manifest.schemaVersion, 1);
assert.equal(manifest.task, "M11-01");
assert.equal(manifest.blenderVersion, "5.2.0");
assert.deepEqual(manifest.domains.map((domain) => domain.domain), [...expected.keys()]);
let total = 0;
const parityCounts = { COMPLETE: 0, PARTIAL: 0, BLOCKED: 0 };
for (const domain of manifest.domains) {
assert.deepEqual(domain.fields.map((field) => field.path).sort(), expected.get(domain.domain));
assert.equal(new Set(domain.fields.map((field) => field.path)).size, domain.fields.length);
assert.ok(Array.isArray(domain.evidence) && domain.evidence.length >= 4);
for (const evidence of domain.evidence) assert.ok(fs.existsSync(path.join(root, evidence)), `${domain.domain} evidence is missing: ${evidence}`);
for (const field of domain.fields) {
for (const stage of stages) assert.ok(stageStates.has(field[stage]), `${domain.domain}.${field.path}.${stage} is invalid`);
assert.ok(parityStates.has(field.parity), `${domain.domain}.${field.path}.parity is invalid`);
if (field.parity === "COMPLETE") {
assert.ok(stages.every((stage) => field[stage] === "VERIFIED" || field[stage] === "NOT_APPLICABLE"), `${domain.domain}.${field.path} overclaims COMPLETE`);
}
parityCounts[field.parity] += 1;
total += 1;
}
}
const requiredBlocks = [
["CAMERA", "orthoScale", "viewportMain"],
["CAMERA", "depthOfField.enabled", "viewportMain"],
["LIGHT", "areaSpread", "viewportMain"],
["LIGHT", "sunAngle", "viewportOffscreen"],
["WORLD", "environmentRotation", "reader"],
["SCENE_COLOR_MANAGEMENT", "colorManagement.displayDevice", "viewportMain"],
["SCENE_COLOR_MANAGEMENT", "colorManagement.gamma", "viewportOffscreen"],
];
for (const [domainName, fieldPath, stage] of requiredBlocks) {
const field = manifest.domains.find((domain) => domain.domain === domainName)?.fields.find((candidate) => candidate.path === fieldPath);
assert.equal(field?.[stage], "BLOCKED", `${domainName}.${fieldPath}.${stage} must remain BLOCKED`);
}
assert.equal(total, 60);
process.stdout.write(`lighting-field-parity-ok fields=${total} complete=${parityCounts.COMPLETE} partial=${parityCounts.PARTIAL} blocked=${parityCounts.BLOCKED}\n`);