import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const readJson = (relative) => JSON.parse(fs.readFileSync(path.join(root, relative), "utf8")); const writeJson = (relative, value) => { const target = path.join(root, relative); fs.mkdirSync(path.dirname(target), { recursive: true }); fs.writeFileSync(target, `${JSON.stringify(value, null, 2)}\n`); }; const report = readJson("tests/golden/WBV2-P1424-001/product-implementation-report.json"); const catalog = readJson("web/app/src/capabilities/blender-feature-route-catalog.json"); const wasmManifest = readJson("web/app/public/wasm-module-manifest.json"); // One representative production check per implementation task. The selector is // deliberately explicit: the runner groups selectors by file, but never retries // a case or runs a second selector for the same feature. const selectors = { "WEBUI-NONMESH-ADVANCED": ["playwright", "tests/e2e/wbv2-nonmesh-delete-production.spec.ts", "WBV2-P1101-000 preserves deleteNonMeshData Main recovery semantics"], "WEBUI-FONT-ASSETS": ["playwright", "tests/e2e/wbv2-font-advanced-production.spec.ts", "WBV2-P1136-001 preserves Font advanced fields and links through Main recovery"], "WEBUI-SCULPT": ["playwright", "tests/e2e/wbv2-sculpt-stroke-production.spec.ts", "WBV2-P1121-000 preserves bounded Sculpt stroke Main mutation"], "WEBUI-NLA-STRIP": ["playwright", "tests/e2e/wbv2-nla-stack-production.spec.ts", "WBV2-P1112-000 preserves setNLAStack Main submission and rejects invalid actions"], "NATIVE-OPERATOR-BRIDGE": ["playwright", "tests/e2e/wbv2-native-engine-production.spec.ts", "WBV2-P10-002 reaches the compiled Blender WASM Main through Chromium"], "WEBUI-OPERATOR-PALETTE": ["playwright", "tests/e2e/smoke.spec.ts", "operator search executes context-filtered workspace, mode and Main commands"], "MESH-EXTENDED-AUTHORING": ["playwright", "tests/e2e/wbv2-primitive-cube-batch-production.spec.ts", "native primitive cube batch preserves Main mutation and recovery"], "MODIFIER-STACK-AUTHORING": ["playwright", "tests/e2e/wbv2-modifier-production.spec.ts", "WBV2-P9-002 production Chromium Modifier receipt is exact and fail-closed"], "NODE-GRAPH-AUTHORING": ["playwright", "tests/e2e/wbv2-geometry-nodes-production.spec.ts", "WBV2-P13-002 binds Geometry Nodes graph evidence to compiled WASM Main"], "RIG-POSE-AUTHORING": ["playwright", "tests/e2e/wbv2-rig-pose-production.spec.ts", "WBV2-P13-003 binds rig pose and skin evidence to compiled WASM Main"], "ACTION-MARKER-AUTHORING": ["playwright", "tests/e2e/wbv2-action-pose-markers-production.spec.ts", "WBV2 Action pose markers are read from Blender Main and survive recovery/reopen"], "SEQUENCER-AUTHORING": ["playwright", "tests/e2e/sequencer-codec-probe.spec.ts", "M11-09 probes IMAGE, SOUND and MOVIE bytes at runtime without extension guessing"], "IO-ROUTE-COMPLETION": ["playwright", "tests/e2e/io-format-operator-production.spec.ts", "WBV2-P1109 binds Blender 5.2 IO operators to Chromium format behavior"], "SCULPT-ADVANCED-AUTHORING": ["playwright", "tests/e2e/wbv2-paint-attributes-production.spec.ts", "WBV2-P16-002 binds paint attributes to compiled WASM Main"], "OBJECT-EDITOR-COVERAGE": ["playwright", "tests/e2e/wbv2-object-transform-production.spec.ts", "WBV2-P23-002 binds applyObjectTransform to compiled WASM Main"], "MESH-EDITOR-COVERAGE": ["playwright", "tests/e2e/wbv2-mesh-production.spec.ts", "WBV2-P9-001 production Chromium Mesh receipt is exact and fail-closed"], "CURVE-SURFACE-COVERAGE": ["playwright", "tests/e2e/wbv2-surface-topology-production.spec.ts", "WBV2-P1134-001 preserves Surface topology transactions through Main recovery and reopen"], "ARMATURE-EDITOR-COVERAGE": ["playwright", "tests/e2e/nla-operator.spec.ts", "M10-12 moves one NLA strip through Main, undo, redo and save/reopen"], "ANIMATION-FCURVE-DRIVER-COVERAGE": ["playwright", "tests/e2e/wbv2-driver-reader-production.spec.ts", "WBV2 driver data is read from Blender Main and survives recovery/reopen"], "SEQUENCER-COMPOSITOR-COVERAGE": ["playwright", "tests/e2e/compositor-main-reader-production.spec.ts", "WBV2-P1104-000 reads compositor NodeTree and links from Blender Main without JS execution"], "PHYSICS-SIMULATION-COVERAGE": ["playwright", "tests/e2e/wbv2-physics-manifest-production.spec.ts", "WBV2-P1117-000 preserves Physics manifest Main persistence and validation"], "TRACKING-MASK-COVERAGE": ["playwright", "tests/e2e/tracking-mask-production.spec.ts", "WBV2-P1127 reads Blender Mask data and selection context in Chromium"], "GREASE-PENCIL-COVERAGE": ["playwright", "tests/e2e/wbv2-grease-pencil-strokes-production.spec.ts", "WBV2-P1114-000 preserves Grease Pencil stroke edits through recovery and reopen"], "RENDER-CAMERA-LIGHT-COVERAGE": ["playwright", "tests/e2e/wbv2-lighting-fields-production.spec.ts", "WBV2-P15-002 binds camera, light, and world fields to compiled WASM Main"], "ASSET-LIBRARY-COVERAGE": ["playwright", "tests/e2e/wbv2-asset-link-override-production.spec.ts", "WBV2-P11-003 enforces linked ownership and local append through compiled WASM Main"], "RNA-DATABLOCK-REFLECTION": ["playwright", "tests/e2e/main-datablocks-reader-production.spec.ts", "WBV2 source reader exposes Blender Main datablock collections without JS simulation"], "SERVER-OPERATOR-JOB": ["command", "node --test web/tests/unit/server-job-result-binding.test.mjs"], "OPERATOR-ROUTE-PALETTE": ["playwright", "tests/e2e/io-format-ui-gate.spec.ts", "M12-05C exposes only matrix-declared file and operator routes"], "OPERATOR-MACRO-COMPOSER": ["command", "node tools/web/check-web-engine-command-registry.mjs"], "RNA-REFLECTION-EXTENDED": ["playwright", "tests/e2e/wbv2-scene-settings-expanded-production.spec.ts", "WBV2-P1129-001 covers the remaining Scene settings Main commands"], "FEATURE-COVERAGE-DASHBOARD": ["command", "python3 my-tools/show_blender_web_scheduler.py"], "SERVER-OPERATOR-HTTP-PROVIDER": ["command", "node --check tools/web/server-operator-job-server.mjs && python3 -m py_compile tools/web/server-operator-job.py"], "SERVER-OPERATOR-SCHEMA-PALETTE": ["playwright", "tests/e2e/wbv2-texture-properties-production.spec.ts", "WBV2-P1139-001 preserves Texture properties through Main recovery and reopen"], "BROWSER-EQUIVALENT-RUNTIME": ["command", "node tools/web/check-blender-feature-route-catalog.mjs"], }; if (report.status !== "implemented" || report.implementationTasks.length !== 34) { throw new Error("product implementation report is not the closed 34-task report"); } const cases = report.implementationTasks.map((task, index) => { const selector = selectors[task.id]; if (!selector) throw new Error(`missing one-pass smoke selector for ${task.id}`); const [kind, fileOrCommand, title] = selector; const route = task.commands?.some((command) => /ServerOperator|serverOperator|renderFrame|renderAnimation/u.test(command)) ? "SERVER_NATIVE" : task.id === "BROWSER-EQUIVALENT-RUNTIME" ? "BROWSER_EQUIVALENT" : "WEB_MAIN"; return { ordinal: index + 1, smokeId: `WBV2-SMOKE-${task.id}`, featureId: task.id, module: task.module, representativeCommand: task.commands?.[0] ?? null, route, kind, ...(kind === "playwright" ? { testFile: fileOrCommand, testTitle: title } : { command: fileOrCommand }), runOnce: true, maxAttempts: 1, status: "PLANNED", }; }); const smokePlan = { schemaVersion: 1, planId: "WBV2-FEATURE-SMOKE-001", operation: "ONE_PASS_FEATURE_SMOKE", policy: { browser: "chromium-only", oneSmokePerFeature: true, retryFailedFeature: false, failureAction: "stop-after-report-and-create-focused-fix-task", scope: "one representative positive/reachability smoke per implemented product feature; negative gates remain assertions of the selected production test", excluded: ["full API matrix", "performance soak", "security/fuzz matrix", "cross-browser", "repeat of already passed feature"], }, inventory: { productFeatures: cases.length, workflowModules: report.workflowModules.length, sourceUnits: catalog.unitCount, routeCounts: catalog.counts, behavioralEvidence: catalog.behavioralEvidence, wasmModules: wasmManifest.modules.map(({ id, lifecycle, preload }) => ({ id, lifecycle, preload })), }, cases, }; writeJson("tests/golden/WBV2/feature-smoke-plan.json", smokePlan); process.stdout.write(`wbv2-feature-smoke-plan-written cases=${cases.length} modules=${report.workflowModules.length} sourceUnits=${catalog.unitCount}\n`);