feat(web): open full feature implementation queue
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

This commit is contained in:
mes123456
2026-09-06 06:14:28 +08:00
parent 03e10698de
commit 7e3f6da78b
17 changed files with 53481 additions and 33 deletions

View File

@@ -15,9 +15,9 @@
| 字段 | 值 |
| --- | --- |
| 里程碑 | WBV2 capability workflow |
| 当前任务 | `WBV2-P1420-001` |
| parent manifest | `tests/golden/WBV2-P1420-000/manifest.json` |
| 任务卡 | [`tasks/WBV2-P1420-001.md`](tasks/WBV2-P1420-001.md) |
| 当前任务 | `WBV2-P1421-001` |
| parent manifest | `tests/golden/WBV2-P1421-000/manifest.json` |
| 任务卡 | [`tasks/WBV2-P1421-001.md`](tasks/WBV2-P1421-001.md) |
| 专项验收 | `node tools/web/check-execution-control-plane.mjs` |
| legacy coverage checkpoint | `M16-GAP-00282` |
| legacy coverage parent | `tests/golden/M16-GAP-00281/manifest.json` |

View File

@@ -4,4 +4,4 @@
- workflow modules: `16/16`
- implementation tasks: `4/4`
- verification: `deferred_until_user_reports`
- nextTask: `NONE`
- nextTask: `WBV2-P1421-000`

View File

@@ -0,0 +1,5 @@
# WBV2-P1421-000 status
- task: `WBV2-P1421-000`; status: `done`
- strategy: `implementation_first_user_feedback`
- nextTask: `WBV2-P1421-001`

View File

@@ -0,0 +1,20 @@
# WBV2-P1421-000: authorize implementation-first Web migration
- task: WBV2-P1421-000
- parent: WBV2-P1420-001
- status: done
- targetImplementationClass: QUEUE_ONLY
- Implementation entrypoint: `python3 my-tools/activate_web_product_migration.py`
## 目标
Replace source-symbol verification batches with the user-workflow implementation backlog.
## Inputs
- `docs/WEB_PRODUCT_MIGRATION_STRATEGY.md`
- `tests/golden/WBV2/web-product-backlog.json`
## Handoff
- nextTask: `WBV2-P1421-001`

View File

@@ -0,0 +1,43 @@
# WBV2-P1421-001: complete Web product workflow implementation
- task: WBV2-P1421-001
- parent: WBV2-P1421-000
- status: in_progress
- gap: product-workflow:user-reachable-main-commands
- ownerFamily: WEB_PRODUCT
- targetImplementationClass: PRODUCT_WORKFLOW
- commandBudget: one implementation subtask per Codex turn
- Implementation entrypoint: `python3 my-tools/run_web_product_migration.py`
## 目标
Complete the implementation tasks in `tests/golden/WBV2/web-product-backlog.json`.
The `3745` source-unit inventory is traceability-only and is not the completion denominator.
## 输入与范围
- `web/app/src/app/App.tsx`
- direct typed protocol helpers named by the active backlog task
- `docs/WEB_PRODUCT_MIGRATION_STRATEGY.md`
## 验收
- implement exactly one backlog task per Codex turn
- preserve existing dirty changes
- do not run tests, builds, typecheck, browsers, validators, or coverage binding
- do not claim similarly named desktop operators
- outer scheduler owns subtask rotation
- `node tools/web/print-task-context.mjs`
## 失败边界
- a failed Codex turn remains pending and is retried without advancing the backlog
- unrelated dirty files are never reverted or included in an automatic commit
- no implementation task changes the source traceability ledger
## 交付与回滚
All workflow modules are implementation-complete. Runtime defects are opened from user operation.
- Backlog: `tests/golden/WBV2/web-product-backlog.json`
- Report: `tests/golden/WBV2-P1421-001/product-implementation-report.json`
- Rollback: stop `my-tools/run_web_product_migration.py` and retain the last completed subtask.

View File

@@ -12,9 +12,9 @@ from pathlib import Path
from wbv2_runtime import CONTROL_ROOT, INDEX, QUEUE, ROOT
CURRENT = "WBV2-P1419-001"
ROOT_TASK = "WBV2-P1420-000"
TASK = "WBV2-P1420-001"
CURRENT = "WBV2-P1420-001"
ROOT_TASK = "WBV2-P1421-000"
TASK = "WBV2-P1421-001"
def read_json(path: Path) -> dict:
@@ -40,6 +40,9 @@ def rel(path: Path) -> str:
def main() -> int:
backlog = read_json(CONTROL_ROOT / "web-product-backlog.json")
pending_tasks = [task for task in backlog.get("tasks", []) if task.get("status") != "implemented"]
source_paths = list(dict.fromkeys(path for task in pending_tasks for path in task.get("ownedPaths", [])))
index = read_json(INDEX)
source_plan_path = ROOT / index["source"]["path"]
plan = read_json(source_plan_path)
@@ -95,10 +98,11 @@ def main() -> int:
"ready": True,
"queueMutationAllowed": True,
"productBacklog": "tests/golden/WBV2/web-product-backlog.json",
"module": {"sourcePaths": source_paths},
}
product_plan = {
**plan,
"planId": "BLENDER_WEB_PRODUCT_IMPLEMENTATION_P1420",
"planId": "BLENDER_WEB_FULL_FEATURE_IMPLEMENTATION_P1421",
"status": "ACTIVE_PRODUCT_IMPLEMENTATION",
"verificationPolicy": {
"mode": "DEFERRED_TO_USER_OPERATION",
@@ -140,7 +144,7 @@ Replace source-symbol verification batches with the user-workflow implementation
- commandBudget: one implementation subtask per Codex turn
- Implementation entrypoint: `python3 my-tools/run_web_product_migration.py`
## Goal
## 目标
Complete the implementation tasks in `tests/golden/WBV2/web-product-backlog.json`.
The `3745` source-unit inventory is traceability-only and is not the completion denominator.
@@ -168,7 +172,7 @@ The `3745` source-unit inventory is traceability-only and is not the completion
## 交付与回滚
All 16 workflow modules are implementation-complete. Runtime defects are opened from user operation.
All workflow modules are implementation-complete. Runtime defects are opened from user operation.
- Backlog: `tests/golden/WBV2/web-product-backlog.json`
- Report: `tests/golden/{TASK}/product-implementation-report.json`
- Rollback: stop `my-tools/run_web_product_migration.py` and retain the last completed subtask.
@@ -180,8 +184,8 @@ All 16 workflow modules are implementation-complete. Runtime defects are opened
"operation": "AUTHORIZE_WEB_PRODUCT_IMPLEMENTATION",
"status": "PASS",
"sourceInventoryRole": "traceability_only",
"workflowModuleCount": 16,
"implementationTaskCount": 4,
"workflowModuleCount": len(backlog.get("workflowModules", [])),
"implementationTaskCount": len(pending_tasks),
"nextTask": TASK,
})
write_json(root_manifest, {
@@ -207,7 +211,7 @@ All 16 workflow modules are implementation-complete. Runtime defects are opened
task_dir.mkdir(parents=True, exist_ok=True)
subprocess.run(["node", "tools/web/generate-v2-task-index.mjs", "--plan-path", rel(plan_path)], cwd=ROOT, check=True)
subprocess.run(["node", "tools/web/check-task-context.mjs", "--task", TASK, "--write"], cwd=ROOT, check=True)
print(f"web-product-queue-activated task={TASK} modules=16 implementationTasks=4")
print(f"web-product-queue-activated task={TASK} modules={len(backlog.get('workflowModules', []))} implementationTasks={len(pending_tasks)}")
return 0

View File

@@ -93,8 +93,8 @@ def refresh_modules(backlog: dict) -> None:
def finalize_product_task(backlog: dict) -> None:
task_id = "WBV2-P1420-001"
parent_id = "WBV2-P1420-000"
task_id = str(backlog.get("queueTask", "WBV2-P1420-001"))
parent_id = str(backlog.get("rootTask", "WBV2-P1420-000"))
index = read_json(CONTROL / "task-index.json")
plan_path = ROOT / index["source"]["path"]
plan = read_json(plan_path)
@@ -132,7 +132,7 @@ def finalize_product_task(backlog: dict) -> None:
"sourceInventory": backlog.get("sourceInventory"),
})
status_path.write_text(
f"# {task_id} status\n\n- status: `implemented`\n- workflow modules: `16/16`\n- implementation tasks: `{len(backlog.get('tasks', []))}/{len(backlog.get('tasks', []))}`\n- verification: `deferred_until_user_reports`\n- nextTask: `NONE`\n",
f"# {task_id} status\n\n- status: `implemented`\n- workflow modules: `{len(backlog.get('workflowModules', []))}/{len(backlog.get('workflowModules', []))}`\n- implementation tasks: `{len(backlog.get('tasks', []))}/{len(backlog.get('tasks', []))}`\n- verification: `deferred_until_user_reports`\n- nextTask: `NONE`\n",
encoding="utf-8",
)
artifacts = {
@@ -185,6 +185,8 @@ def write_status(backlog: dict, status: str, **extra: object) -> None:
def prompt(task: dict) -> str:
backlog = read_json(BACKLOG)
queue_task = str(backlog.get("queueTask", "WBV2-P1420-001"))
return f"""Implement exactly one Web Blender product workflow task in {ROOT}.
Task: {task['id']} - {task['title']}
@@ -194,7 +196,7 @@ Implementation requirement: {task['implementation']}
Rules:
- Follow the repository AGENTS.md minimal-context instructions first.
- The authoritative queue task is WBV2-P1420-001; this product task is one bounded subtask inside it. Run the default task-context check once, and never pass the product subtask id to check-task-context.
- The authoritative queue task is {queue_task}; this product task is one bounded subtask inside it. Run the default task-context check once, and never pass the product subtask id to check-task-context.
- Preserve all existing dirty changes. Do not revert or rewrite unrelated work.
- Read only the owned paths and their direct imported types/helpers.
- For scoped searches, pass each owned path explicitly through the batch search runtime option; never pass a bare --runtime flag.

View File

@@ -48,14 +48,15 @@ def main() -> int:
product = status["progress"].get("productMigration", {})
product_pid = product.get("pid")
product_alive = isinstance(product_pid, int) and (Path("/proc") / str(product_pid)).exists()
product_complete = (
product.get("workflowTotal", 0) > 0
and product.get("workflowImplemented") == product.get("workflowTotal")
and product.get("taskImplemented") == product.get("taskTotal")
)
status["myTools"]["productMigrationAlive"] = product_alive
status["unattendedState"] = (
"IMPLEMENTING" if product_alive and product.get("status") == "implementing"
else "COMPLETE" if product.get("status") == "implementation_complete" or (
product.get("workflowTotal", 0) > 0
and product.get("workflowImplemented") == product.get("workflowTotal")
and product.get("taskImplemented") == product.get("taskTotal")
)
else "COMPLETE" if product_complete
else "BLOCKED" if product.get("status") == "blocked"
else "PLANNING" if status.get("state") == "IDLE" and watchdog_alive and watchdog.get("status") == "waiting_for_source_batch"
else status.get("state", "UNKNOWN")

View File

@@ -25,7 +25,7 @@
},
"status": {
"path": "docs/status/WBV2-P1420-001.md",
"sha256": "0db7d7b3d4cbc14367a50746c88f98d5729e4d9dcb50f68b9dda0c29602fc81a"
"sha256": "8106d2b06025af35d59ec5318368a364d29c0d3cd966251bb3c3b60ffa519fac"
},
"plan": {
"path": "tests/golden/WBV2-P1420-000/product-implementation-plan.json",
@@ -36,5 +36,5 @@
"sha256": "6924f578fb38bc40c4fb26b0d18ea32fbf635cfd8cff0316128bc2448a5fdd56"
}
},
"nextTask": null
"nextTask": "WBV2-P1421-000"
}

View File

@@ -0,0 +1,26 @@
{
"schemaVersion": 1,
"task": "WBV2-P1421-000",
"parentTask": "WBV2-P1420-001",
"operation": "AUTHORIZE_WEB_PRODUCT_IMPLEMENTATION",
"status": "done",
"artifacts": {
"parentManifest": {
"path": "tests/golden/WBV2-P1420-001/manifest.json",
"sha256": "c34b56ba0dcb3209bc26081b33b91c42182471e772c518b95a98aa7a873e6b92"
},
"plan": {
"path": "tests/golden/WBV2-P1421-000/product-implementation-plan.json",
"sha256": "24baf7b9b1995f5c763a13f3baa708089ac6e60b8006deadbd8445479d859531"
},
"report": {
"path": "tests/golden/WBV2-P1421-000/product-migration-authorization.json",
"sha256": "968badd0bd5ca49b46bb6243b4572cdf0fed241253b99f17e9004dd1f01ae88c"
},
"status": {
"path": "docs/status/WBV2-P1421-000.md",
"sha256": "abbac0ee42e7d90fc6a3ae669cb933e4717cc87237b9bf41576a5926acb8b485"
}
},
"nextTask": "WBV2-P1421-001"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
{
"schemaVersion": 1,
"task": "WBV2-P1421-000",
"operation": "AUTHORIZE_WEB_PRODUCT_IMPLEMENTATION",
"status": "PASS",
"sourceInventoryRole": "traceability_only",
"workflowModuleCount": 16,
"implementationTaskCount": 10,
"nextTask": "WBV2-P1421-001"
}

View File

@@ -0,0 +1,199 @@
{
"schemaVersion": 1,
"task": "WBV2-P1421-001",
"parentTask": "WBV2-P1421-000",
"status": "in_progress",
"goal": "Complete the implementation tasks in `tests/golden/WBV2/web-product-backlog.json`.",
"scope": {
"gap": "product-workflow:user-reachable-main-commands",
"ownerFamily": "WEB_PRODUCT",
"implementationClass": "PRODUCT_WORKFLOW"
},
"commands": [
"node tools/web/print-task-context.mjs"
],
"inputPaths": [
"docs/WEB_PRODUCT_MIGRATION_STRATEGY.md"
],
"inputMetadata": {
"docs/EXECUTION_QUEUE.md": {
"path": "docs/EXECUTION_QUEUE.md",
"exists": true,
"bytes": 4030,
"mtime_ns": "1788646326569103190",
"sha256": "66d3e1246589e1c10d45b8fe2e714118c1ec42cdb874372efb1c3b3dbace46dc"
},
"docs/tasks/WBV2-P1421-001.md": {
"path": "docs/tasks/WBV2-P1421-001.md",
"exists": true,
"bytes": 1640,
"mtime_ns": "1788646380785590700",
"sha256": "595c89678f27477aa5baf62449a039dcd0746affe4d54cdf6bd4f548e4429411"
},
"tests/golden/WBV2-P1421-000/manifest.json": {
"path": "tests/golden/WBV2-P1421-000/manifest.json",
"exists": true,
"bytes": 911,
"mtime_ns": "1788646326568916212",
"sha256": "bf6c3f96d28a0ba1af8232f844fceae27b245bad6bedccd86b89fac6723a2963"
},
"docs/status/WBV2-P1421-000.md": {
"path": "docs/status/WBV2-P1421-000.md",
"exists": true,
"bytes": 144,
"mtime_ns": "1788646326567669290",
"sha256": "abbac0ee42e7d90fc6a3ae669cb933e4717cc87237b9bf41576a5926acb8b485"
},
"docs/WEB_PRODUCT_MIGRATION_STRATEGY.md": {
"path": "docs/WEB_PRODUCT_MIGRATION_STRATEGY.md",
"exists": true,
"bytes": 3066,
"mtime_ns": "1788640338290223181",
"sha256": "b0086cf81a52c71b9efdd764c005d65de7fe48a8f013ce6405a76486bf2310e6"
}
},
"inputSelection": {
"schemaVersion": 1,
"limits": {
"maxFiles": 12,
"evidenceBytes": 8192,
"contextRemainingBytes": 3179,
"contextRemainingTokens": 794
},
"source": {
"bytes": 6725,
"tokens": 1682
},
"selected": [
{
"path": "docs/WEB_PRODUCT_MIGRATION_STRATEGY.md",
"bytes": 3066,
"tokens": 767
}
],
"excluded": [
{
"path": "tests/golden/WBV2/web-product-backlog.json",
"bytes": 15709,
"reason": "EVIDENCE_BYTE_BUDGET"
},
{
"path": "web/app/src/app/App.tsx",
"bytes": 249654,
"reason": "EVIDENCE_BYTE_BUDGET"
},
{
"path": "tests/golden/WBV2-P1421-001/product-implementation-report.json",
"bytes": null,
"reason": "MISSING_PATH"
}
],
"totals": {
"files": 1,
"bytes": 3066,
"tokens": 767
}
},
"exitCriteria": [
"focused command exits 0",
"report and manifest are hash-bound",
"failure path does not publish a late result"
],
"nextTask": null,
"sourceDocuments": {
"queue": "docs/EXECUTION_QUEUE.md",
"taskCard": "docs/tasks/WBV2-P1421-001.md",
"taskIndex": "tests/golden/WBV2/task-index.json",
"parentManifest": "tests/golden/WBV2-P1421-000/manifest.json",
"parentStatus": "docs/status/WBV2-P1421-000.md"
},
"readPolicy": {
"required": [
"docs/EXECUTION_QUEUE.md",
"docs/tasks/WBV2-P1421-001.md",
"tests/golden/WBV2-P1421-000/manifest.json",
"docs/status/WBV2-P1421-000.md"
],
"machineOnly": [
"tests/golden/WBV2/task-index.json",
"tests/golden/M15-03A/task-catalog.jsonl"
],
"optionalByNeed": [
"docs/WEB_BLENDER_MODELER_V1_SCOPE.md",
"任务卡列出的精确协议/生产路径",
"任务卡明确命名的长期计划小节"
],
"forbiddenByDefault": [
"完整 CURRENT_EXECUTION_PLAN.md",
"完整 PROJECT_STATUS_AND_NEXT_WORK.md",
"全部 docs/status/*.md",
"完整 parity/WBS 计划",
"README 历史和 test-results/"
]
},
"parent": {
"manifest": {
"schemaVersion": 1,
"task": "WBV2-P1421-000",
"parentTask": "WBV2-P1420-001",
"status": "done",
"nextTask": "WBV2-P1421-001",
"artifactCount": 4
},
"statusSummary": [
"# WBV2-P1421-000 status",
"- task: `WBV2-P1421-000`; status: `done`",
"- strategy: `implementation_first_user_feedback`",
"- nextTask: `WBV2-P1421-001`"
]
},
"budgets": {
"queueBytes": 4096,
"taskBytes": 1640,
"parentManifestBytes": 24576,
"parentStatusBytes": 6144,
"evidenceFiles": 12,
"evidenceBytes": 8192,
"contextTokens": 3500,
"contextEnvelopeTokens": 1024,
"taskLines": 44,
"taskTokens": 410
},
"size": {
"documents": [
{
"path": "docs/EXECUTION_QUEUE.md",
"bytes": 4030,
"lines": 58,
"tokens": 1008
},
{
"path": "docs/tasks/WBV2-P1421-001.md",
"bytes": 1640,
"lines": 44,
"tokens": 410
},
{
"path": "tests/golden/WBV2-P1421-000/manifest.json",
"bytes": 911,
"lines": 27,
"tokens": 228
},
{
"path": "docs/status/WBV2-P1421-000.md",
"bytes": 144,
"lines": 6,
"tokens": 36
}
],
"sourceTokens": 1682,
"evidenceFiles": 1,
"evidenceBytes": 3066,
"evidenceTokens": 767,
"totalTokens": 2449,
"reservedEnvelopeTokens": 1024,
"estimatedContextTokens": 3473,
"serializedContextTokens": 641,
"withinBudget": true
}
}

View File

@@ -619,3 +619,5 @@
{"id":"WBV2-P1419-001","gapId":"MESH_MERGE_MACRO_BATCH","ownerFamily":"MESH","sourceTask":"1419","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["source and protocol hashes are bound","every selected Main reader type is proven","negative no-mutation and recovery are proven","Chromium and save/reopen evidence are exact"]}
{"id":"WBV2-P1420-000","gapId":"workflow:authorize implementation-first Web product migration","ownerFamily":"PROGRAM","sourceTask":"1420","state":"completed","targetImplementationClass":"QUEUE_ONLY"}
{"id":"WBV2-P1420-001","gapId":"workflow:complete user-facing Web workflow implementation","ownerFamily":"WEB_PRODUCT","sourceTask":"1420","state":"completed","targetImplementationClass":"PRODUCT_WORKFLOW"}
{"id":"WBV2-P1421-000","gapId":"workflow:authorize implementation-first Web product migration","ownerFamily":"PROGRAM","sourceTask":"1420","state":"completed","targetImplementationClass":"QUEUE_ONLY"}
{"id":"WBV2-P1421-001","gapId":"workflow:complete user-facing Web workflow implementation","ownerFamily":"WEB_PRODUCT","sourceTask":"1420","state":"active","targetImplementationClass":"PRODUCT_WORKFLOW"}

File diff suppressed because one or more lines are too long

View File

@@ -2,6 +2,9 @@
"schemaVersion": 1,
"strategy": "implementation_first_user_feedback",
"verificationPolicy": "deferred_until_user_reports",
"previousQueueTask": "WBV2-P1420-001",
"rootTask": "WBV2-P1421-000",
"queueTask": "WBV2-P1421-001",
"sourceInventory": {
"unitCount": 3745,
"role": "traceability_only",
@@ -16,17 +19,27 @@
{
"id": "WORKSPACE",
"title": "Web workspace and viewport",
"status": "implemented"
"status": "partial",
"taskIds": [
"NATIVE-OPERATOR-BRIDGE",
"WEBUI-OPERATOR-PALETTE"
]
},
{
"id": "OBJECT",
"title": "Object and scene graph",
"status": "implemented"
"status": "partial",
"taskIds": [
"NATIVE-OPERATOR-BRIDGE"
]
},
{
"id": "MESH",
"title": "Mesh modeling and UV",
"status": "implemented"
"status": "partial",
"taskIds": [
"MESH-EXTENDED-AUTHORING"
]
},
{
"id": "NONMESH",
@@ -45,14 +58,20 @@
{
"id": "MODIFIER",
"title": "Modifiers and geometry nodes",
"status": "implemented"
"status": "partial",
"taskIds": [
"MODIFIER-STACK-AUTHORING",
"NODE-GRAPH-AUTHORING"
]
},
{
"id": "ANIMATION",
"title": "Animation and NLA",
"status": "implemented",
"taskIds": [
"WEBUI-NLA-STRIP"
"WEBUI-NLA-STRIP",
"RIG-POSE-AUTHORING",
"ACTION-MARKER-AUTHORING"
]
},
{
@@ -60,7 +79,8 @@
"title": "Sculpt, paint and Grease Pencil",
"status": "implemented",
"taskIds": [
"WEBUI-SCULPT"
"WEBUI-SCULPT",
"SCULPT-ADVANCED-AUTHORING"
]
},
{
@@ -81,12 +101,18 @@
{
"id": "MEDIA",
"title": "Media, audio and sequencer",
"status": "implemented"
"status": "partial",
"taskIds": [
"SEQUENCER-AUTHORING"
]
},
{
"id": "ASSET_IO",
"title": "Assets, libraries and interchange",
"status": "implemented"
"status": "partial",
"taskIds": [
"IO-ROUTE-COMPLETION"
]
},
{
"id": "STORAGE",
@@ -179,6 +205,188 @@
"implementation": "Add context-aware NLA track/strip selection and frame-start editing to the Timeline, using the existing typed moveNLAStrip command.",
"startedAt": "2026-09-05T21:37:32.541259+00:00",
"completedAt": "2026-09-05T21:44:42.999869+00:00"
},
{
"id": "NATIVE-OPERATOR-BRIDGE",
"module": "WORKSPACE",
"title": "Add an allowlisted native Blender operator bridge",
"status": "pending",
"attempts": 0,
"commands": ["listBlenderOperators", "invokeBlenderOperator"],
"ownedPaths": [
"web/protocol/web-engine.ts",
"web/protocol/web-engine-capabilities.ts",
"web/app/src/workers/web-engine.worker.ts",
"blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
"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/CMakeLists.txt"
],
"resultPath": "tests/golden/WBV2/product-migration/NATIVE-OPERATOR-BRIDGE-result.json",
"implementation": "Implement a source-backed operator catalog and invocation command for background-safe Blender operators. Use explicit allowlisting, typed JSON properties, context/poll checks, Main transaction rollback, revision updates, and scene refresh. UI/window/file-browser operators must be rejected and left to browser-native workflows."
},
{
"id": "WEBUI-OPERATOR-PALETTE",
"module": "WORKSPACE",
"title": "Expose the native operator catalog in the Web command palette",
"status": "pending",
"attempts": 0,
"commands": ["listBlenderOperators", "invokeBlenderOperator"],
"ownedPaths": [
"web/app/src/app/App.tsx",
"web/app/src/engine-client/WebEngineClient.ts",
"web/protocol/blender-operator.ts",
"web/protocol/web-engine.ts"
],
"resultPath": "tests/golden/WBV2/product-migration/WEBUI-OPERATOR-PALETTE-result.json",
"implementation": "Load the native background-safe operator catalog and merge it into F3 search. Add a compact typed property form for boolean, number, enum, and string properties, with an explicit execute action and no generic arbitrary JSON console."
},
{
"id": "MESH-EXTENDED-AUTHORING",
"module": "MESH",
"title": "Complete common primitive and mesh authoring workflows",
"status": "pending",
"attempts": 0,
"commands": ["createPrimitive", "meshEdit", "invokeBlenderOperator"],
"ownedPaths": [
"web/protocol/web-engine.ts",
"web/protocol/core-scene-commands.ts",
"web/protocol/mesh-authoring-commands.ts",
"web/app/src/app/App.tsx",
"blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
"blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp"
],
"resultPath": "tests/golden/WBV2/product-migration/MESH-EXTENDED-AUTHORING-result.json",
"implementation": "Expose plane, UV sphere, ico sphere, cylinder, cone and torus creation plus subdivide, fill, triangulate, recalculate normals, bridge loops and delete mesh elements. Reuse the native operator bridge where a direct Main writer is not already present."
},
{
"id": "MODIFIER-STACK-AUTHORING",
"module": "MODIFIER",
"title": "Add complete modifier stack authoring controls",
"status": "pending",
"attempts": 0,
"commands": ["addModifier", "removeModifier", "moveModifier", "setModifierParameters"],
"ownedPaths": [
"web/protocol/web-engine.ts",
"web/protocol/modifier.ts",
"web/app/src/app/App.tsx",
"web/app/src/workers/web-engine.worker.ts",
"blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
"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"
],
"resultPath": "tests/golden/WBV2/product-migration/MODIFIER-STACK-AUTHORING-result.json",
"implementation": "Add native commands and Web controls to add, remove, reorder and edit supported modifier parameters. Drive available types and fields from existing modifier metadata rather than hard-coded test fixtures."
},
{
"id": "NODE-GRAPH-AUTHORING",
"module": "MODIFIER",
"title": "Add node graph creation and editing workflows",
"status": "pending",
"attempts": 0,
"commands": ["setGeometryNodeGraph", "setShaderGraph"],
"ownedPaths": [
"web/app/src/app/App.tsx",
"web/protocol/geometry-node-commands.ts",
"web/protocol/geometry-nodes.ts",
"web/protocol/shader-graph-commands.ts",
"web/protocol/shader-graph.ts"
],
"resultPath": "tests/golden/WBV2/product-migration/NODE-GRAPH-AUTHORING-result.json",
"implementation": "Provide usable graph controls for adding/removing nodes, connecting/disconnecting sockets, editing values, and committing Geometry/Shader graphs through the existing native full-graph commands."
},
{
"id": "RIG-POSE-AUTHORING",
"module": "ANIMATION",
"title": "Add armature, bone and pose authoring",
"status": "pending",
"attempts": 0,
"commands": ["setArmatureBones", "setPoseBoneTransform"],
"ownedPaths": [
"web/protocol/web-engine.ts",
"web/protocol/scene-ir.ts",
"web/app/src/app/App.tsx",
"web/app/src/workers/web-engine.worker.ts",
"blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
"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"
],
"resultPath": "tests/golden/WBV2/product-migration/RIG-POSE-AUTHORING-result.json",
"implementation": "Implement native armature bone creation/editing and pose transforms with parent relationships, roll, head/tail and transform controls, then expose them for the active armature in the Properties workspace."
},
{
"id": "ACTION-MARKER-AUTHORING",
"module": "ANIMATION",
"title": "Complete Action, keyframe and timeline marker workflows",
"status": "pending",
"attempts": 0,
"commands": ["createAction", "removeAction", "setKeyframe", "setTimelineMarkers"],
"ownedPaths": [
"web/protocol/web-engine.ts",
"web/protocol/animation-render-commands.ts",
"web/protocol/scene-ir.ts",
"web/app/src/app/App.tsx",
"web/app/src/workers/web-engine.worker.ts",
"blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
"blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp"
],
"resultPath": "tests/golden/WBV2/product-migration/ACTION-MARKER-AUTHORING-result.json",
"implementation": "Add user workflows for creating/removing Actions, editing individual keyframe values/handles/interpolation, and adding, renaming, moving and deleting timeline markers through native Main commands."
},
{
"id": "SEQUENCER-AUTHORING",
"module": "MEDIA",
"title": "Complete sequencer strip editing",
"status": "pending",
"attempts": 0,
"commands": ["setSequencerStrips"],
"ownedPaths": [
"web/protocol/web-engine.ts",
"web/protocol/sequencer.ts",
"web/app/src/app/App.tsx",
"web/app/src/sequencer/SequencerTimeline.ts",
"web/app/src/workers/web-engine.worker.ts",
"blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
"blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp"
],
"resultPath": "tests/golden/WBV2/product-migration/SEQUENCER-AUTHORING-result.json",
"implementation": "Expose add, remove, move, trim, split, mute and channel editing for scene, movie, sound, image and meta strips. Commit the complete bounded strip list to Blender Main and retain existing browser media proxy services."
},
{
"id": "IO-ROUTE-COMPLETION",
"module": "ASSET_IO",
"title": "Complete browser file import and export routes",
"status": "pending",
"attempts": 0,
"commands": ["importScene", "exportScene"],
"ownedPaths": [
"web/app/src/app/App.tsx",
"web/protocol/io-format-ui-gate.ts",
"web/protocol/io-media-commands.ts",
"web/app/src/capabilities/io-format-ui-registry.json",
"web/app/src/workers/web-engine.worker.ts",
"blender-5.2.0/source/blender/web_engine/web_engine_api.cpp"
],
"resultPath": "tests/golden/WBV2/product-migration/IO-ROUTE-COMPLETION-result.json",
"implementation": "Connect browser file pickers and downloads for the locally available GLB/glTF, OBJ, STL and PLY routes, preserve explicit loss reports, and route formats requiring unavailable native libraries to the existing server job provider."
},
{
"id": "SCULPT-ADVANCED-AUTHORING",
"module": "PAINT",
"title": "Complete advanced sculpt workflows",
"status": "pending",
"attempts": 0,
"commands": ["sculptStroke", "setSculptMeshAttributes", "invokeBlenderOperator"],
"ownedPaths": [
"web/app/src/app/App.tsx",
"web/protocol/paint.ts",
"web/protocol/sculpt.ts",
"web/app/src/workers/web-engine.worker.ts",
"blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
"blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp"
],
"resultPath": "tests/golden/WBV2/product-migration/SCULPT-ADVANCED-AUTHORING-result.json",
"implementation": "Add cursor-derived multi-sample strokes, mask and face-set operations, symmetry, smooth/inflate/grab controls, and remesh entry points using native commands or the allowlisted operator bridge."
}
]
}

View File

@@ -50,6 +50,24 @@ const runtimeAllowlist = new Set([
"web/protocol/paint.ts",
"web/protocol/sculpt.ts",
"web/app/src/fonts/external-vfont-import.ts",
"web/app/src/workers/web-engine.worker.ts",
"web/protocol/web-engine-capabilities.ts",
"web/protocol/blender-operator.ts",
"web/protocol/core-scene-commands.ts",
"web/protocol/mesh-authoring-commands.ts",
"web/protocol/modifier.ts",
"web/protocol/geometry-node-commands.ts",
"web/protocol/geometry-nodes.ts",
"web/protocol/shader-graph-commands.ts",
"web/protocol/shader-graph.ts",
"web/protocol/sequencer.ts",
"web/protocol/io-format-ui-gate.ts",
"web/protocol/io-media-commands.ts",
"web/app/src/sequencer/SequencerTimeline.ts",
"web/app/src/capabilities/io-format-ui-registry.json",
"blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
"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",
]);
const runtimePaths = [];
for (let index = 0; index < process.argv.length; index += 1) {