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 abs = (file) => path.join(root, file); const read = (file) => fs.readFileSync(abs(file), "utf8"); const json = (file) => JSON.parse(read(file)); const sha = (file) => crypto.createHash("sha256").update(fs.readFileSync(abs(file))).digest("hex"); const writeJson = (file, value) => { fs.mkdirSync(path.dirname(abs(file)), { recursive: true }); fs.writeFileSync(abs(file), `${JSON.stringify(value, null, 2)}\n`); }; const writeText = (file, value) => { fs.mkdirSync(path.dirname(abs(file)), { recursive: true }); fs.writeFileSync(abs(file), value); }; if (!process.argv.includes("--write")) { console.log("usage: node tools/web/reorganize-wbv2-module-execution.mjs --write"); process.exit(1); } const queuePath = "docs/EXECUTION_QUEUE.md"; const inventoryPath = "tests/golden/WBV2-P0-002/parity-map.json"; const previousTask = "WBV2-P1096-000"; const previousParent = "tests/golden/WBV2-P1095-003/manifest.json"; const bridgeManifestPath = `tests/golden/${previousTask}/manifest.json`; const rootTask = "WBV2-P1100-000"; const firstModuleTask = "WBV2-P1100-001"; const planPath = `tests/golden/${rootTask}/module-execution-plan.json`; const rootReportPath = `tests/golden/${rootTask}/module-execution-root-report.json`; const rootStatusPath = `docs/status/${rootTask}.md`; const rootManifestPath = `tests/golden/${rootTask}/manifest.json`; const inventory = json(inventoryPath); const parent = json(previousParent); assert.equal(parent.status, "done"); assert.equal(parent.nextTask, previousTask); const bridgeReportPath = `tests/golden/${previousTask}/module-queue-bridge-report.json`; const bridgeStatusPath = `docs/status/${previousTask}.md`; writeJson(bridgeReportPath, { schemaVersion: 1, task: previousTask, operation: "SUPERSEDE_GENERIC_CONTINUATION_QUEUE", status: "PASS", parent: { task: parent.task, manifest: previousParent, manifestSha256: sha(previousParent) }, decision: { superseded: true, parityStateChange: false, noCapabilityClaim: true, reason: "The generated continuation queue repeated existing markers without a module contract.", replacementRoot: rootTask, }, inventory: { total: inventory.summary.inventoryEntries, pending: inventory.summary.pendingLegacyEntries, effectiveCompleted: 290, effectivePending: 6609 }, nextTask: rootTask, }); writeText(bridgeStatusPath, `# ${previousTask} status\n\n- task: \`${previousTask}\`; parent: \`${parent.task}\`; status: \`done\`\n- operation: \`SUPERSEDE_GENERIC_CONTINUATION_QUEUE\`\n- no Blender capability completion claimed; repeated continuation is replaced by module execution\n- inventory unchanged: \`6900\` total, effective \`290/6609\`\n- nextTask: \`${rootTask}\`\n`); writeJson(bridgeManifestPath, { schemaVersion: 1, task: previousTask, parentTask: parent.task, operation: "SUPERSEDE_GENERIC_CONTINUATION_QUEUE", status: "done", enablingTask: true, parityStateChange: false, runtime: "MODULE_EXECUTION_QUEUE_BRIDGE", artifacts: { parentManifest: { path: previousParent, sha256: sha(previousParent) }, report: { path: bridgeReportPath, sha256: sha(bridgeReportPath) }, status: { path: bridgeStatusPath, sha256: sha(bridgeStatusPath) }, }, assertions: { supersededGenericContinuation: true, noCapabilityClaim: true, inventoryTotal: 6900, effectiveCompleted: 290, effectivePending: 6609, historicalReproduction: false, }, nextTask: rootTask, }); const source = { core: [ "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "web/protocol/web-engine.ts", "web/app/src/workers/web-engine.worker.ts", ], render: [ "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "web/protocol/scene-ir.ts", "web/protocol/web-engine.ts", "web/app/src/workers/web-engine.worker.ts", "web/app/src/app/App.tsx", "web/app/src/vendor/blender/web_engine.wasm", ], }; const receipts = (tasks) => tasks.map((task) => ({ manifest: `tests/golden/${task}/manifest.json`, report: `tests/golden/${task}/implementation-report.json`, })); const moduleTask = ({ id, moduleId, owner, parentId, status, ready, title, capabilities, sourcePaths, reuseReceipts, positive, negative, recovery, commands, sourceBacked = true }) => ({ id, phase: id.match(/^WBV2-P(\d+)/u)?.[1] ?? "1100", title, kind: "module", owner, dependsOn: [parentId], parityId: moduleId, implementationClass: "LOCAL_EXACT", parallelGroup: `module-${moduleId.toLowerCase()}`, gate: "MODULE", card: `docs/tasks/${id}.md`, behavior: `Complete the ${moduleId} module through its shared Blender Main primitives and aggregate case matrix.`, outputs: ["module receipt", "negative matrix", "manifest", "status"], acceptance: ["source and protocol hashes are bound", "positive Main mutation is proven", "negative and recovery cases are proven", "Chromium and save/reopen receipts are exact", "full-family parity remains explicit"], status, ready, queueMutationAllowed: true, module: { moduleId, sourceBacked, capabilities, sourcePaths, reuseReceipts, positive, negative, recovery, commands, fullFamilyParity: false }, }); const moduleTasks = [ moduleTask({ id: firstModuleTask, moduleId: "RENDER_LIGHT_CAMERA", owner: "RENDER", parentId: rootTask, status: "in_progress", ready: true, title: "verify_render_light_camera_module", capabilities: ["CAP-RENDER-LIGHT-TYPE", "CAP-RENDER-LIGHT-AREA-SHAPE", "CAP-RENDER-LIGHT-CONTRIBUTION-FACTORS", "CAP-RENDER-LIGHT-SHADOW-CONTROLS", "CAP-RENDER-LIGHT-CASCADE-CONTROLS", "CAP-RENDER-LIGHT-AREA-SIZE-Z", "CAP-RENDER-LIGHT-CLIP-START", "CAP-RENDER-WORLD-LIGHTING-CONTROLS", "CAP-RENDER-WORLD-PROBE-CONTROLS", "CAP-RENDER-WORLD-ENVIRONMENT-STRENGTH", "CAP-RENDER-CAMERA-DOF-FOCUS-OBJECT", "CAP-RENDER-CAMERA-PANORAMA"], sourcePaths: source.render, reuseReceipts: receipts(["WBV2-P595-002", "WBV2-P596-002", "WBV2-P597-002", "WBV2-P598-002", "WBV2-P599-002", "WBV2-P600-002", "WBV2-P601-002", "WBV2-P602-002", "WBV2-P603-002", "WBV2-P604-002", "WBV2-P605-002", "WBV2-P606-002"]), positive: ["setLightProperties", "setWorldProperties", "setCameraProperties", "camera panorama", "world environment", "light shadow/cascade"], negative: ["invalid enum", "invalid numeric bounds", "near/far conflict", "unknown target", "stale revision"], recovery: ["undo", "redo", "save/reopen", "worker disposal"], commands: [ "npm --prefix web run typecheck", "npm --prefix web run test:lighting-field-roundtrip", "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-lighting-fields-production.spec.ts tests/e2e/lighting-field-roundtrip.spec.ts", ], }), moduleTask({ id: "WBV2-P1100-002", moduleId: "SCENE_OBJECT_MESH", owner: "SCENE_MESH", parentId: firstModuleTask, status: "planned", ready: false, title: "verify_scene_object_mesh_module", capabilities: ["CAP-MESH-TOPOLOGY-FAMILY", "CAP-CORE-SCENE-OBJECT", "CAP-OBJECT-MOVE-COLLECTION"], sourcePaths: source.core, reuseReceipts: [{ manifest: "tests/golden/WBV2-P11-001/manifest.json", report: "tests/golden/WBV2-P11-001/mesh-topology-receipt-report.json" }, { manifest: "tests/golden/WBV2-P12-002/manifest.json", report: "tests/golden/WBV2-P12-002/scene-object-receipt-report.json" }, { manifest: "tests/golden/WBV2-P24-002/manifest.json", report: "tests/golden/WBV2-P24-002/object-move-receipt-report.json" }], positive: ["mesh topology", "visibility", "transform", "collection membership"], negative: ["invalid selection", "stale revision", "linked data"], recovery: ["undo", "redo", "save/reopen"], commands: ["npm --prefix web run typecheck", "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-mesh-topology-production.spec.ts tests/e2e/wbv2-scene-object-production.spec.ts"], }), moduleTask({ id: "WBV2-P1100-003", moduleId: "MATERIAL_ANIMATION", owner: "MATERIAL_ANIMATION", parentId: "WBV2-P1100-002", status: "planned", ready: false, title: "verify_material_animation_module", capabilities: ["CAP-MATERIAL-ANIMATION"], sourcePaths: source.core, reuseReceipts: [{ manifest: "tests/golden/WBV2-P12-003/manifest.json", report: "tests/golden/WBV2-P12-003/material-animation-receipt-report.json" }], positive: ["principled material", "image node", "keyframe", "FCurve"], negative: ["unsupported graph", "stale revision"], recovery: ["undo", "redo", "save/reopen"], commands: ["npm --prefix web run typecheck", "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-material-animation-production.spec.ts"], }), moduleTask({ id: "WBV2-P1101-000", moduleId: "NONMESH_GEOMETRY", owner: "GEOMETRY", parentId: "WBV2-P1100-003", status: "planned", ready: false, title: "verify_nonmesh_geometry_module", capabilities: ["CAP-VIEWPORT-NONMESH", "CAP-NATIVE-DATABLOCK"], sourcePaths: source.core, reuseReceipts: [{ manifest: "tests/golden/WBV2-P12-004/manifest.json", report: "tests/golden/WBV2-P12-004/viewport-nonmesh-receipt-report.json" }, { manifest: "tests/golden/WBV2-P29-003/manifest.json", report: "tests/golden/WBV2-P29-003/implementation-report.json" }], positive: ["curve", "surface", "font", "volume", "metaball", "grease pencil"], negative: ["unsupported data", "resource missing", "malformed geometry"], recovery: ["save/reopen", "resource disposal"], commands: ["npm --prefix web run typecheck", "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-viewport-nonmesh-production.spec.ts"], }), moduleTask({ id: "WBV2-P1101-001", moduleId: "NODES_SIMULATION", owner: "NODES_SIMULATION", parentId: "WBV2-P1101-000", status: "planned", ready: false, title: "verify_nodes_simulation_module", capabilities: ["CAP-GEOMETRY-NODES", "CAP-SIMULATION"], sourcePaths: source.core, reuseReceipts: [{ manifest: "tests/golden/WBV2-P13-002/manifest.json", report: "tests/golden/WBV2-P13-002/geometry-nodes-receipt-report.json" }, { manifest: "tests/golden/WBV2-P13-004/manifest.json", report: "tests/golden/WBV2-P13-004/advanced-domain-receipt-report.json" }], positive: ["allowlisted node graph", "physics manifest", "stable hash"], negative: ["unsupported node", "budget exceeded", "stale revision"], recovery: ["save/reopen", "cache disposal"], commands: ["npm --prefix web run test:geometry-node-main-reader", "npm --prefix web run test:physics-main-reader"], }), moduleTask({ id: "WBV2-P1101-002", moduleId: "ASSET_IO", owner: "ASSET", parentId: "WBV2-P1101-001", status: "planned", ready: false, title: "verify_asset_io_module", capabilities: ["CAP-ASSET-LINK-OVERRIDE-RELOAD", "CAP-ASSET-CATALOG-MUTATION"], sourcePaths: source.core, reuseReceipts: [{ manifest: "tests/golden/WBV2-P11-003/manifest.json", report: "tests/golden/WBV2-P11-003/asset-link-override-receipt-report.json" }, { manifest: "tests/golden/WBV2-P10-003/manifest.json", report: "tests/golden/WBV2-P10-003/module-matrix-receipt-report.json" }], positive: ["append", "link", "override", "reload", "asset catalog v2"], negative: ["missing source", "ownership violation", "hash drift", "collision"], recovery: ["undo", "redo", "save/reopen", "IndexedDB restart"], commands: ["npm --prefix web run test:asset-catalog-m12-evidence", "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-asset-link-override-production.spec.ts tests/e2e/wbv2-asset-catalog-production.spec.ts"], }), moduleTask({ id: "WBV2-P1101-003", moduleId: "SCULPT_PAINT", owner: "SCULPT_PAINT", parentId: "WBV2-P1101-002", status: "planned", ready: false, title: "verify_sculpt_paint_module", capabilities: ["CAP-PAINT-ATTRIBUTES", "CAP-SCULPT-PAINT"], sourcePaths: source.core, reuseReceipts: [{ manifest: "tests/golden/WBV2-P16-002/manifest.json", report: "tests/golden/WBV2-P16-002/paint-attributes-receipt-report.json" }], positive: ["vertex colors", "vertex weights", "bounded sculpt stroke"], negative: ["mirror unverified", "invalid patch", "unsupported brush"], recovery: ["undo", "redo", "save/reopen"], commands: ["npm --prefix web run test:paint-roundtrip", "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-paint-attributes-production.spec.ts"], }), moduleTask({ id: "WBV2-P1102-000", moduleId: "UI_EDITOR", owner: "EDITOR", parentId: "WBV2-P1101-003", status: "planned", ready: false, title: "implement_ui_editor_module", capabilities: ["CAP-UI-EDITOR"], sourcePaths: ["web/protocol/editor-workflow.ts", "web/app/src/app/App.tsx", "web/app/src/workers/web-engine.worker.ts"], reuseReceipts: [], sourceBacked: false, positive: ["editor context", "workspace", "area/region"], negative: ["unsupported editor", "invalid context"], recovery: ["worker restart", "save/reopen"], commands: ["npm --prefix web run test:editor-main-reader", "npm --prefix web run typecheck"], }), moduleTask({ id: "WBV2-P1102-001", moduleId: "INVENTORY_GATE", owner: "RELEASE", parentId: "WBV2-P1102-000", status: "planned", ready: false, title: "close_module_execution_gate", capabilities: [], sourcePaths: [inventoryPath, "tests/golden/WBV2-P1100-000/module-execution-plan.json"], reuseReceipts: [], positive: ["aggregate module receipts", "catalog hash"], negative: ["missing receipt", "hash drift", "false completion"], recovery: ["re-run affected module only"], commands: ["node tools/web/check-wbv2-module-execution.mjs", "npm --prefix web run build"], }), ]; const bridgeTask = { id: previousTask, phase: "1096", title: "supersede_generic_continuation_queue", kind: "bridge", owner: "PROGRAM", dependsOn: [parent.task], parityId: null, implementationClass: "QUEUE_ONLY", parallelGroup: "bridge", gate: "QUEUE", card: `docs/tasks/${previousTask}.md`, behavior: "Replace the generic continuation queue with a finite module execution plan without claiming capability parity.", outputs: ["bridge manifest", "status"], acceptance: ["no parity claim", "inventory preserved", "module plan hash-bound"], status: "done", ready: false, queueMutationAllowed: true, }; const rootRecord = { id: rootTask, phase: "1100", title: "reorganize_module_execution_plan", kind: "enabling", owner: "PROGRAM", dependsOn: [previousTask], parityId: null, implementationClass: "QUEUE_ONLY", parallelGroup: "module-root", gate: "MODULE", card: `docs/tasks/${rootTask}.md`, behavior: "Reuse completed source-backed work and activate finite module-level implementation and verification.", outputs: ["module plan", "manifest", "status"], acceptance: ["completed receipts reused", "generic continuation excluded", "one module active", "inventory preserved"], status: "done", ready: false, queueMutationAllowed: true, }; const tasks = [bridgeTask, rootRecord, ...moduleTasks]; const plan = { schemaVersion: 1, planId: "BLENDER_WEB_MODULE_EXECUTION_EPOCH_3", operation: "FUNCTION_MODULE_MIGRATION_PLAN", status: "ACTIVE_MODULE_EXECUTION_QUEUE", authority: "blender_main_source_and_existing_hash_bound_receipts", executionPointer: queuePath, inventory: { path: inventoryPath, sha256: sha(inventoryPath), total: 6900, legacyCompleted: 281, legacyPending: 6618, effectiveCompleted: 290, effectivePending: 6609, mutation: "forbidden_by_module_execution" }, reusePolicy: { completedReceipts: "reuse_without_rerun", continuationEvidence: "excluded", duplicateValidation: "forbidden", fullFamilyParity: "never_inferred" }, verificationPolicy: { browser: "chromium_only", required: ["sourceHash", "wasmBuild", "positiveMainMutation", "negativeNoMutation", "undoRedo", "saveReopen", "aggregateManifest"], failure: "keep_module_in_progress_and_do_not_advance" }, modules: moduleTasks.map((task) => ({ id: task.module.moduleId, task: task.id, owner: task.owner, sourceBacked: task.module.sourceBacked, capabilities: task.module.capabilities, reusedReceipts: task.module.reuseReceipts, fullFamilyParity: false })), tasks, }; writeJson(planPath, plan); writeText(`docs/tasks/${rootTask}.md`, `# ${rootTask}: reorganize_module_execution_plan\n\n- task: ${rootTask}\n- parent: ${previousTask}\n- status: done\n- gap: workflow:function_module_migration_plan\n- ownerFamily: PROGRAM\n- targetImplementationClass: QUEUE_ONLY\n\n## 目标\n\nReuse completed source-backed Blender work and switch execution to finite function/module workflows.\n\n## 输入与范围\n\n- Existing receipts: \`tests/golden/WBV2-P10-002/\`, \`tests/golden/WBV2-P11-004/\`, \`tests/golden/WBV2-P12-005/\`, \`tests/golden/WBV2-P13-005/\`, \`tests/golden/WBV2-P595-002/\` through \`tests/golden/WBV2-P606-002/\`\n- Module plan: \`${planPath}\`\n- Validator: \`node tools/web/check-wbv2-module-execution.mjs\`\n\n## 验收\n\n- completed receipts are reused and hash-checked\n- generic continuation evidence is excluded from productive module claims\n- one module task is active\n- inventory remains 6900 / effective 290/6609\n\n## 交付与回滚\n\n- Manifest: \`${rootManifestPath}\`\n- Rollback: restore ${previousTask} as queue parent without rewriting prior receipts.\n`); for (const task of moduleTasks) { const module = task.module; const receiptLines = module.reuseReceipts.length === 0 ? "- None; source-backed implementation must be established before activation" : module.reuseReceipts.map((item) => `- \`${item.manifest}\`\n- \`${item.report}\``).join("\n"); writeText(`docs/tasks/${task.id}.md`, `# ${task.id}: ${task.title}\n\n- task: ${task.id}\n- parent: ${task.dependsOn[0]}\n- status: ${task.status}\n- gap: workflow:module_${module.moduleId.toLowerCase()}\n- ownerFamily: ${task.owner}\n- targetImplementationClass: LOCAL_EXACT\n- moduleId: ${module.moduleId}\n\n## 目标\n\nComplete one coherent Blender function module through shared Main primitives and an aggregate operator case matrix.\n\n## 输入与范围\n\n- Source paths:\n${module.sourcePaths.map((item) => `- \`${item}\``).join("\n")}\n- Reused receipts:\n${receiptLines}\n- Implementation and verification entrypoint: \`node tools/web/run-wbv2-module-task.mjs --task ${task.id} --write\`\n\n## 验证\n\nPositive cases: ${module.positive.join(", ")}\nNegative boundaries: ${module.negative.join(", ")}\nRecovery: ${module.recovery.join(", ")}\nCommands:\n${module.commands.map((item) => `- \`${item}\``).join("\n")}\n\nA module advances only when source hashes, positive Main mutation, negative no-mutation, undo/redo, save/reopen, Chromium and aggregate manifest checks pass. A representative case never claims full-family parity.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/${task.id}/\`\n- Manifest: \`tests/golden/${task.id}/manifest.json\`\n- Status: \`docs/status/${task.id}.md\`\n- Rollback: restore ${task.dependsOn[0]} as queue parent and leave this module in_progress.\n`); writeText(`docs/status/${task.id}.md`, `# ${task.id} status\n\n- task: \`${task.id}\`; parent: \`${task.dependsOn[0]}\`; status: \`${task.status}\`\n- module: \`${module.moduleId}\`; sourceBacked: \`${module.sourceBacked}\`; fullFamilyParity: \`false\`\n- positive/negative/recovery verification is required before handoff\n- inventory remains: \`6900\` total, effective \`290/6609\`\n- nextTask: \`${tasks[tasks.findIndex((candidate) => candidate.id === task.id) + 1]?.id ?? "NONE"}\`\n`); } writeJson(rootReportPath, { schemaVersion: 1, task: rootTask, operation: "REORGANIZE_FUNCTION_MODULE_EXECUTION", status: "PASS", parent: { task: previousTask, manifest: bridgeManifestPath, manifestSha256: sha(bridgeManifestPath) }, reused: { completedModuleReceipts: ["WBV2-P10-002", "WBV2-P10-003", "WBV2-P11-001", "WBV2-P11-002", "WBV2-P11-003", "WBV2-P11-004", "WBV2-P12-002", "WBV2-P12-003", "WBV2-P12-004", "WBV2-P13-002", "WBV2-P13-003", "WBV2-P13-004", "WBV2-P15-002", "WBV2-P16-002", "WBV2-P24-002", "WBV2-P595-002..WBV2-P606-002"], noRerun: true }, modules: moduleTasks.length, activeModule: firstModuleTask, verification: plan.verificationPolicy, inventory: plan.inventory, nextTask: firstModuleTask, }); writeText(rootStatusPath, `# ${rootTask} status\n\n- task: \`${rootTask}\`; parent: \`${previousTask}\`; status: \`done\`\n- execution model: \`FUNCTION_MODULE_MIGRATION\`\n- completed source/WASM/Chromium receipts reused without rerun\n- modules planned: \`${moduleTasks.length}\`; active module: \`${moduleTasks[0].module.moduleId}\`\n- verification requires source hash, Main mutation, negative no-mutation, undo/redo, save/reopen, Chromium and aggregate manifest\n- inventory unchanged: \`6900\` total, effective \`290/6609\`\n- nextTask: \`${firstModuleTask}\`\n`); writeJson(rootManifestPath, { schemaVersion: 1, task: rootTask, parentTask: previousTask, operation: "REORGANIZE_FUNCTION_MODULE_EXECUTION", status: "done", enablingTask: true, parityStateChange: false, runtime: "FUNCTION_MODULE_MIGRATION_QUEUE", artifacts: { parentManifest: { path: bridgeManifestPath, sha256: sha(bridgeManifestPath) }, plan: { path: planPath, sha256: sha(planPath) }, report: { path: rootReportPath, sha256: sha(rootReportPath) }, status: { path: rootStatusPath, sha256: sha(rootStatusPath) }, }, assertions: { moduleCount: moduleTasks.length, completedReceiptsReused: true, genericContinuationExcluded: true, inventoryTotal: 6900, effectiveCompleted: 290, effectivePending: 6609, verificationPolicyBound: true, fullFamilyParity: false, historicalReproduction: false }, nextTask: firstModuleTask, }); execFileSync(process.execPath, [abs("tools/web/generate-v2-task-index.mjs"), "--plan-path", abs(planPath)], { cwd: root, stdio: "inherit" }); let queue = read(queuePath); queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, `| 当前任务 | \`${firstModuleTask}\` |`) .replace(/\| parent manifest \| `[^`]+` \|/u, `| parent manifest | \`${rootManifestPath}\` |`) .replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, `| 任务卡 | [\`tasks/${firstModuleTask}.md\`](tasks/${firstModuleTask}.md) |`); writeText(queuePath, queue); execFileSync(process.execPath, [abs("tools/web/check-task-context.mjs"), "--task", previousTask, "--write"], { cwd: root, stdio: "inherit" }); execFileSync(process.execPath, [abs("tools/web/check-task-context.mjs"), "--task", rootTask, "--write"], { cwd: root, stdio: "inherit" }); execFileSync(process.execPath, [abs("tools/web/check-task-context.mjs"), "--task", firstModuleTask, "--write"], { cwd: root, stdio: "inherit" }); let next = read("nextTask.md"); const tick = String.fromCharCode(96); next = next.replace(/\| Current task when this file was written \| `[^`]+` \|/u, `| Current task when this file was written | ${tick}${firstModuleTask}${tick} |`) .replace(/\| Current task state \| `[^`]+` \|/u, `| Current task state | ${tick}in_progress${tick} |`) .replace(/\| Parent manifest \| `[^`]+` \|/u, `| Parent manifest | ${tick}${rootManifestPath}${tick} |`) .replace(/\| Current task card \| `[^`]+` \|/u, `| Current task card | ${tick}docs/tasks/${firstModuleTask}.md${tick} |`) .replace(/\| Current task-context nextTask \| `[^`]+` \|/u, `| Current task-context nextTask | ${tick}WBV2-P1100-002${tick} |`) .replace(/\| Focused command \| `[^`]+` \|/u, `| Focused command | ${tick}node tools/web/run-wbv2-module-task.mjs --task ${firstModuleTask} --write${tick} |`); writeText("nextTask.md", next); console.log(`module-execution-plan-written root=${rootTask} active=${firstModuleTask} modules=${moduleTasks.length} reusedReceipts=true inventory=6900 effectivePending=6609`);