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 read = (file) => fs.readFileSync(path.join(root, file), "utf8"); const report = JSON.parse(read("tests/golden/WBV2-P1424-001/product-implementation-report.json")); const registry = read("web/protocol/web-engine-capabilities.ts"); const registered = new Set([...registry.matchAll(/^ ([A-Za-z0-9]+): \{/gmu)].map((match) => match[1])); const directJson = new Set([ "listBlenderOperators", "invokeBlenderOperator", "listBlenderMacros", "invokeBlenderMacro", "importScene", "exportScene", "assetMark", "assetCatalog", "libraryLink", "libraryOverride", "libraryReload", "listRNADataBlocks", "readRNAProperties", "setRNAProperty", "listRNACollections", "readRNAPropertySchema", "setRNAArrayProperty", "setRNAEnumProperty", "readRNACollection", "submitServerOperatorJob", "cancelServerOperatorJob", "readServerOperatorResult", ]); const routed = new Set(["listFeatureRoutes", "invokeFeatureRoute", "featureRouteCoverage", "featureRouteGaps", "describeServerOperator", "invokeBrowserEquivalent", "featureRouteRuntimeAudit"]); const owners = new Map(); for (const task of report.implementationTasks) { for (const command of task.commands ?? []) { const list = owners.get(command) ?? []; list.push({ taskId: task.id, module: task.module }); owners.set(command, list); } } const commands = [...owners].sort(([left], [right]) => left.localeCompare(right)); const cases = commands.map(([command, bindings], index) => { const mode = directJson.has(command) ? "WASM_JSON_ROUTE" : registered.has(command) ? "WASM_EDIT_ROUTE" : routed.has(command) ? "RUNTIME_ROUTE" : null; if (!mode) throw new Error(`no submodule smoke route for ${command}`); return { ordinal: index + 1, smokeId: `WBV2-SUBMODULE-SMOKE-${command}`, submoduleId: command, bindings, mode, runOnce: true, maxAttempts: 1, status: "PLANNED", }; }); const plan = { schemaVersion: 1, planId: "WBV2-INTERNAL-SUBMODULE-SMOKE-001", operation: "ONE_PASS_INTERNAL_SUBMODULE_SMOKE", policy: { identity: "one unique product command equals one internal submodule", oneSmokePerSubmodule: true, retryFailedSubmodule: false, wasmPolicy: "dispatch each native command once against the source-matched production WASM; malformed minimal input must be recognized and fail closed", runtimePolicy: "non-WASM browser/server routes must resolve to their concrete Client, Worker, provider or UI adapter", fixPolicy: "record failures once, fix only failed submodules, and use a separate focused-fix report", }, inventory: { productTasks: report.implementationTasks.length, commandBindings: [...owners.values()].reduce((sum, bindings) => sum + bindings.length, 0), uniqueSubmodules: cases.length, byMode: Object.fromEntries([...new Set(cases.map((item) => item.mode))].sort().map((mode) => [mode, cases.filter((item) => item.mode === mode).length])), }, cases, }; const output = path.join(root, "tests/golden/WBV2/internal-submodule-smoke-plan.json"); fs.writeFileSync(output, `${JSON.stringify(plan, null, 2)}\n`); process.stdout.write(`wbv2-submodule-smoke-plan-written submodules=${cases.length} bindings=${plan.inventory.commandBindings} wasm=${cases.filter((item) => item.mode.startsWith("WASM_")).length} runtime=${cases.filter((item) => item.mode === "RUNTIME_ROUTE").length}\n`);