Files
workinf_Blender_Wasm/tools/web/generate-wbv2-lights-root.mjs
mes123456 4a5c70910b
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
Advance deduplicated lighting capability coverage
2026-08-28 12:19:18 +08:00

54 lines
14 KiB
JavaScript

import assert from "node:assert/strict";
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import { execFileSync } from "node:child_process";
import { fileURLToPath } from "node:url";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
const absolute = (file) => path.join(root, file);
const read = (file) => fs.readFileSync(absolute(file), "utf8");
const json = (file) => JSON.parse(read(file));
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex");
const p14ManifestPath = "tests/golden/WBV2-P14-003/manifest.json";
const p14ReportPath = "tests/golden/WBV2-P14-003/inventory-coverage-gate-report.json";
const p14StatusPath = "docs/status/WBV2-P14-003.md";
const p15Root = "tests/golden/WBV2-P15-000";
const planPath = `${p15Root}/lights-task-plan.json`;
const reportPath = `${p15Root}/lights-root-report.json`;
const manifestPath = `${p15Root}/manifest.json`;
const statusPath = "docs/status/WBV2-P15-000.md";
const sourceMapPath = "tests/golden/WBV2-P0-002/parity-map.json";
const sourceTestPath = "web/tests/e2e/lighting-field-roundtrip.spec.ts";
const sourceCommandPath = "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp";
const p14 = json(p14ManifestPath); const p14Report = json(p14ReportPath); const sourceMap = json(sourceMapPath);
assert.equal(p14.task, "WBV2-P14-003"); assert.equal(p14.status, "done"); assert.equal(p14.nextTask, null); assert.equal(p14Report.status, "PASS"); assert.equal(p14Report.decision.inventoryPending, 6618); assert.equal(sourceMap.summary.inventoryEntries, 6900);
for (const artifact of Object.values(p14.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
const tasks = [
{ id: "WBV2-P15-000", phase: "P15", title: "authorize_lighting_capability_continuation", kind: "enabling", owner: "PROGRAM", dependsOn: ["WBV2-P14-003"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p15-governance", gate: "G2", card: "docs/tasks/WBV2-P15-000.md", behavior: "Authorize a source-backed Lighting/Camera/World capability slice without reopening completed batches.", outputs: ["continuation root", "candidate scope", "hash boundary"], acceptance: ["P14 coverage remains hash-bound", "source command and Chromium test exist", "one production task is active"], status: "done", ready: false, queueMutationAllowed: true },
{ id: "WBV2-P15-001", phase: "P15", title: "select_lighting_capability_batch", kind: "enabling", owner: "PARITY", dependsOn: ["WBV2-P15-000"], parityId: "RENDER.LIGHTING_FIELDS", implementationClass: "LOCAL_BOUNDED", parallelGroup: "p15-selection", gate: "G2", card: "docs/tasks/WBV2-P15-001.md", behavior: "Select one deterministic Lighting/Camera/World behavior batch from existing source and tests.", outputs: ["candidate report", "behavior hash", "dedupe key"], acceptance: ["source API is present", "Chromium test is present", "candidate remains representative rather than full-family completion"], status: "in_progress", ready: true, queueMutationAllowed: false },
{ id: "WBV2-P15-002", phase: "P15", title: "lighting_fields_engine_receipt", kind: "feature", owner: "RENDER", dependsOn: ["WBV2-P15-001"], parityId: "RENDER.LIGHTING_FIELDS", implementationClass: "LOCAL_EXACT", parallelGroup: "p15-lighting", gate: "G2", card: "docs/tasks/WBV2-P15-002.md", behavior: "Bind Camera, Light, and World field edits, undo/redo, and exact save/reopen to compiled WASM Main in Chromium.", outputs: ["lighting production report", "lighting receipt", "manifest"], acceptance: ["camera/light/world fields match", "undo/redo revisions are sequential", "save/reopen is exact", "malformed values fail closed"], status: "planned", ready: false, queueMutationAllowed: false },
{ id: "WBV2-P15-003", phase: "P15", title: "close_lighting_capability_gate", kind: "enabling", owner: "RELEASE", dependsOn: ["WBV2-P15-002"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p15-release", gate: "G5", card: "docs/tasks/WBV2-P15-003.md", behavior: "Close the Lighting capability gate while preserving partial-family and 6900-entry limitations.", outputs: ["lighting gate", "limited declaration", "manifest"], acceptance: ["only the tested slice is claimed", "inventory remainder remains 6618", "no repeated validation or historical over-claim"], status: "planned", ready: false, queueMutationAllowed: false },
];
const plan = { schemaVersion: 1, planId: "BLENDER_WEB_PARITY_V2_LIGHTING_EPOCH_1", status: "ACTIVE_LIGHTING_QUEUE", authority: "queue_reactivated_after_p14_coverage_gate", sourcePlan: "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", executionPointer: "docs/EXECUTION_QUEUE.md", runtimePolicy: { blenderSource: "blender-5.2.0", browserEvidence: ["chromium"], forbiddenBrowsers: ["firefox", "webkit"], mainAuthority: "blender_main", reusePolicy: "source_hash_and_behavior_hash_deduplication" }, parentCoverage: { manifest: p14ManifestPath, report: p14ReportPath, inventoryTotal: 6900, inventoryPending: 6618, duplicateValidationAvoided: true }, tasks };
fs.mkdirSync(absolute(p15Root), { recursive: true }); fs.writeFileSync(absolute(planPath), `${JSON.stringify(plan, null, 2)}\n`);
const report = { schemaVersion: 1, task: "WBV2-P15-000", operation: "AUTHORIZE_LIGHTING_CAPABILITY_CONTINUATION", status: "PASS", parent: { task: p14.task, manifest: p14ManifestPath, manifestSha256: sha256(p14ManifestPath), report: p14ReportPath, reportSha256: sha256(p14ReportPath), previousDecision: p14Report.decision.status }, continuation: { root: "WBV2-P15-000", firstTask: "WBV2-P15-001", plannedTasks: 4, candidate: "RENDER.LIGHTING_FIELDS", sourceApi: sourceCommandPath, chromiumTest: sourceTestPath, browser: "chromium", inventoryTotal: 6900, inventoryPending: 6618, noRepeatedExecution: true }, policy: { p14EvidencePreserved: true, sourceHistoryReadOnly: true, representativeSliceOnly: true, duplicateValidationAvoided: true, authorizedRebaselineOnly: true, fullHistoricalReproduction: false }, nextTask: "WBV2-P15-001" };
fs.writeFileSync(absolute(reportPath), `${JSON.stringify(report, null, 2)}\n`);
fs.writeFileSync(absolute("docs/tasks/WBV2-P15-000.md"), `# WBV2-P15-000: lighting capability continuation root\n\n- task: WBV2-P15-000\n- parent: WBV2-P14-003\n- status: done\n- gap: workflow:authorize_lighting_capability_continuation\n- ownerFamily: PROGRAM\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nAuthorize a source-backed Lighting/Camera/World continuation. P15 reuses the 6900-entry coverage ledger and runs only one representative Chromium production slice for fields already exposed by the compiled WebEngine API.\n\n## 验收\n\n- \`node tools/web/generate-wbv2-lights-root.mjs\`\n- \`node tools/web/check-execution-control-plane.mjs\`\n- \`node tools/web/check-v2-task-index.mjs\`\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P15-000/\`\n- Manifest: \`tests/golden/WBV2-P15-000/manifest.json\`\n- Rollback: restore P14-003 as queue parent without rewriting P14 evidence.\n`);
const cards = {
"WBV2-P15-001": `# WBV2-P15-001: select_lighting_capability_batch\n\n- task: WBV2-P15-001\n- parent: WBV2-P15-000\n- status: in_progress\n- gap: capability:RENDER.LIGHTING_FIELDS\n- ownerFamily: PARITY\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nSelect one deterministic Camera, Light, and World field behavior batch from the existing source API and Chromium test.\n\n## 输入与范围\n\n- Focused source: \`blender-5.2.0/source/blender/web_engine/web_engine_api.cpp\`\n- Existing production test: \`web/tests/e2e/lighting-field-roundtrip.spec.ts\`\n- Inventory: \`tests/golden/WBV2-P0-002/parity-map.json\`\n- Production entrypoint: \`node tools/web/generate-wbv2-lighting-selection.mjs --write\`\n\n## 验收\n\n- source API and Chromium test hashes are bound\n- one behavior hash covers camera/light/world fields\n- representative slice is not promoted to full-family parity\n- malformed, hash-drift, unsupported, or false-completion input keeps in_progress\n- \`node tools/web/check-task-context.mjs --task WBV2-P15-001 --write\`\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P15-001/\`\n- Status: \`docs/status/WBV2-P15-001.md\`\n- Manifest: \`tests/golden/WBV2-P15-001/manifest.json\`\n- Rollback: restore P15-000 as queue parent.\n`,
"WBV2-P15-002": `# WBV2-P15-002: lighting_fields_engine_receipt\n\n- task: WBV2-P15-002\n- parent: WBV2-P15-001\n- status: planned\n- gap: capability:RENDER.LIGHTING_FIELDS\n- ownerFamily: RENDER\n- targetImplementationClass: LOCAL_EXACT\n\n## 目标\n\nBind Camera, Light, and World edits, undo/redo, and exact save/reopen to the compiled WASM Main in Chromium.\n\n## 输入与范围\n\n- Focused source: \`tests/golden/WBV2-P15-001/lighting-selection-report.json\`\n- Production test: \`web/tests/e2e/wbv2-lighting-fields-production.spec.ts\`\n- Production entrypoint: \`npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-lighting-fields-production.spec.ts\`\n\n## 验收\n\n- camera/light/world fields match the bounded expected values\n- undo/redo revisions are sequential\n- save/reopen is exact\n- malformed values fail closed without Main mutation\n- Chromium is the only browser\n- \`node tools/web/check-task-context.mjs --task WBV2-P15-002 --write\`\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P15-002/\`\n- Status: \`docs/status/WBV2-P15-002.md\`\n- Manifest: \`tests/golden/WBV2-P15-002/manifest.json\`\n- Rollback: restore P15-001 as queue parent.\n`,
"WBV2-P15-003": `# WBV2-P15-003: close_lighting_capability_gate\n\n- task: WBV2-P15-003\n- parent: WBV2-P15-002\n- status: planned\n- gap: workflow:close_lighting_capability_gate\n- ownerFamily: RELEASE\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nClose the Lighting capability gate while preserving partial-family and 6900-entry limitations.\n\n## 输入与范围\n\n- Focused receipt: \`tests/golden/WBV2-P15-002/lighting-fields-receipt-report.json\`\n- Coverage matrix: \`tests/golden/WBV2-P14-002/capability-evidence-matrix.json\`\n- Production entrypoint: \`node tools/web/generate-wbv2-lighting-gate.mjs --write\`\n\n## 验收\n\n- only the tested lighting slice is claimed\n- pending inventory remains 6618\n- duplicate validation remains zero\n- historical reproduction remains false\n- \`node tools/web/check-task-context.mjs --task WBV2-P15-003 --write\`\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P15-003/\`\n- Status: \`docs/status/WBV2-P15-003.md\`\n- Manifest: \`tests/golden/WBV2-P15-003/manifest.json\`\n- Rollback: restore P15-002 as queue parent.\n`,
};
for (const [id, card] of Object.entries(cards)) fs.writeFileSync(absolute(`docs/tasks/${id}.md`), `${card}\n`);
fs.writeFileSync(absolute(statusPath), `# WBV2-P15-000 status\n\n- task: \`WBV2-P15-000\`; parent: \`WBV2-P14-003\`; status: \`done\`\n- candidate: \`RENDER.LIGHTING_FIELDS\`; source API and Chromium test are present\n- inventory carried forward: \`6900\` total, \`6618\` pending\n- duplicate validation: \`forbidden\`; representative slice only\n- nextTask: \`WBV2-P15-001\`\n\nP15 is an authorized continuation that reuses the P14 coverage ledger and validates one source-backed Camera/Light/World behavior batch in Chromium.\n`);
const artifactPaths = { parentManifest: p14ManifestPath, parentReport: p14ReportPath, sourceMap: sourceMapPath, sourceApi: sourceCommandPath, sourceTest: sourceTestPath, plan: planPath, report: reportPath, rootCard: "docs/tasks/WBV2-P15-000.md", rootStatus: statusPath };
const artifacts = Object.fromEntries(Object.entries(artifactPaths).map(([name, file]) => [name, { path: file, sha256: sha256(file) }]));
const manifest = { schemaVersion: 1, task: "WBV2-P15-000", parentTask: "WBV2-P14-003", operation: "AUTHORIZE_LIGHTING_CAPABILITY_CONTINUATION", status: "done", enablingTask: true, parityStateChange: false, runtime: "READ_ONLY_LIGHTING_CONTINUATION_ROOT", artifacts, assertions: { p14EvidencePreserved: true, sourceApiBound: true, chromiumTestBound: true, inventoryTotal: 6900, inventoryPending: 6618, duplicateValidationAvoided: true, representativeSliceOnly: true, authorizedRebaselineOnly: true, fullHistoricalReproduction: false }, nextTask: "WBV2-P15-001" };
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
execFileSync(process.execPath, [absolute("tools/web/generate-v2-task-index.mjs"), "--plan-path", absolute(planPath)], { cwd: root, stdio: "inherit" });
let queue = read("docs/EXECUTION_QUEUE.md"); queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P15-001` |").replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P15-000/manifest.json` |").replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P15-001.md`](tasks/WBV2-P15-001.md) |"); fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
let nextTask = read("nextTask.md"); nextTask = nextTask.replace(/\| Current task when this file was written \| `[^`]+` \|/u, "| Current task when this file was written | `WBV2-P15-001` |").replace(/\| Current task state \| `[^`]+` \|/u, "| Current task state | `in_progress` |").replace(/\| Parent manifest \| `[^`]+` \|/u, "| Parent manifest | `tests/golden/WBV2-P15-000/manifest.json` |").replace(/\| Current task card \| `[^`]+` \|/u, "| Current task card | `docs/tasks/WBV2-P15-001.md` |").replace(/\| Current task-context nextTask \| `[^`]+` \|/u, "| Current task-context nextTask | `WBV2-P15-002` |").replace(/\| Focused command \| `[^`]+` \|/u, "| Focused command | `node tools/web/generate-wbv2-lighting-selection.mjs --write` |"); fs.writeFileSync(absolute("nextTask.md"), nextTask);
process.stdout.write("wbv2-lights-root-written root=WBV2-P15-000 next=WBV2-P15-001 candidate=RENDER.LIGHTING_FIELDS inventoryPending=6618\n");