diff --git a/my-tools/authorize_next_wbv2_task.py b/my-tools/authorize_next_wbv2_task.py index 32352bd14..ab4cf1521 100644 --- a/my-tools/authorize_next_wbv2_task.py +++ b/my-tools/authorize_next_wbv2_task.py @@ -846,26 +846,17 @@ def auto_operator_macro_batch(inventory: dict) -> dict | None: ] if not units: return None - gates = ( - ("duplicate_move", "OBJECT_DUPLICATE_MACRO_BATCH", "OBJECT", "tests/files/web/basic_scene.blend", "web/tests/e2e/wbv2-object-duplicate-production.spec.ts", "object-duplicate-production.json", None), - ("delete", "OBJECT_DELETE_MACRO_BATCH", "OBJECT", "tests/files/web/basic_scene.blend", "web/tests/e2e/wbv2-object-delete-batch-production.spec.ts", "object-delete-production.json", None), - ("hide_view", "OBJECT_VISIBILITY_MACRO_BATCH", "OBJECT", "tests/files/web/generated/WBV2-P2-002-OBJECT.TRANSFORM_HIERARCHY.blend", "web/tests/e2e/wbv2-object-visibility-clear-batch-production.spec.ts", "object-visibility-clear-production.json", None), - ("location_clear", "OBJECT_LOCATION_CLEAR_MACRO_BATCH", "OBJECT", "tests/files/web/basic_scene.blend", "web/tests/e2e/wbv2-object-transform-clear-batch-production.spec.ts", "object-transform-clear-production.json", "LOCATION"), - ("rotation_clear", "OBJECT_ROTATION_CLEAR_MACRO_BATCH", "OBJECT", "tests/files/web/basic_scene.blend", "web/tests/e2e/wbv2-object-transform-clear-batch-production.spec.ts", "object-transform-clear-production.json", "ROTATION"), - ("scale_clear", "OBJECT_SCALE_CLEAR_MACRO_BATCH", "OBJECT", "tests/files/web/basic_scene.blend", "web/tests/e2e/wbv2-object-transform-clear-batch-production.spec.ts", "object-transform-clear-production.json", "SCALE"), - ("transform_apply", "OBJECT_TRANSFORM_APPLY_MACRO_BATCH", "OBJECT", "tests/files/web/basic_scene.blend", "web/tests/e2e/wbv2-object-transform-apply-batch-production.spec.ts", "object-transform-apply-production.json", None), - ("move_to_collection", "OBJECT_MOVE_COLLECTION_MACRO_BATCH", "OBJECT", "tests/files/web/generated/WBV2-P24-001-OBJECT_OPERATIONS.MOVE_COLLECTION.blend", "web/tests/e2e/wbv2-object-move-batch-production.spec.ts", "object-move-production.json", None), - ("parent_set", "OBJECT_PARENT_MACRO_BATCH", "OBJECT", "tests/files/web/basic_scene.blend", "web/tests/e2e/wbv2-object-parent-production.spec.ts", "object-parent-production.json", None), - ("primitive_cube_add", "MESH_PRIMITIVE_CUBE_MACRO_BATCH", "MESH", "tests/files/web/basic_scene.blend", "web/tests/e2e/wbv2-primitive-cube-batch-production.spec.ts", "primitive-cube-production.json", None), - ("extrude_", "MESH_EXTRUDE_MACRO_BATCH", "MESH", "tests/files/web/generated/WBV2-P2-003-MESH.EDIT_CORE.blend", "web/tests/e2e/wbv2-mesh-topology-production.spec.ts", "mesh-topology-production.json", "EXTRUDE"), - ("loopcut", "MESH_LOOPCUT_MACRO_BATCH", "MESH", "tests/files/web/generated/WBV2-P2-003-MESH.EDIT_CORE.blend", "web/tests/e2e/wbv2-mesh-topology-production.spec.ts", "mesh-topology-production.json", "LOOP_CUT"), - ("dissolve", "MESH_DISSOLVE_MACRO_BATCH", "MESH", "tests/files/web/generated/WBV2-P2-003-MESH.EDIT_CORE.blend", "web/tests/e2e/wbv2-mesh-topology-production.spec.ts", "mesh-topology-production.json", "DISSOLVE"), - ("merge", "MESH_MERGE_MACRO_BATCH", "MESH", "tests/files/web/generated/WBV2-P2-003-MESH.EDIT_CORE.blend", "web/tests/e2e/wbv2-mesh-topology-production.spec.ts", "mesh-topology-production.json", "MERGE"), - ) - for marker, module_id, owner, fixture, test, production_name, operation in gates: + # Names are exact on purpose. Shared words such as "delete" or + # "duplicate" do not prove that a macro from another editor invokes the + # same native command; substring matching would create false coverage. + # No unresolved macro currently has an exact native gate. Keep the table + # empty until a matching fixture and command are added; mapping a macro to + # a merely similar operation would be false coverage. + gates = () + for exact_identifier, module_id, owner, fixture, test, production_name, operation in gates: if not (ROOT / fixture).is_file() or not (ROOT / test).is_file(): continue - selected = next((unit for unit in units if marker in unit["identifier"].lower()), None) + selected = next((unit for unit in units if unit["identifier"] == exact_identifier), None) if not selected: continue return { @@ -901,6 +892,34 @@ def pending_summary(inventory: dict) -> dict: return {"count": len(pending), "byKind": by_kind, "byFamily": by_family, "sample": [unit.get("id") for unit in pending[:12]]} +def write_source_gap_report(inventory: dict) -> None: + """Persist the next bounded source gaps when no exact gate exists. + + This is a planner artifact, not coverage evidence. It gives the unattended + loop a deterministic handoff for the next implementation pass without + marking an unsupported unit as verified or repeatedly rescanning the tree. + """ + pending = [unit for unit in inventory.get("units", []) if isinstance(unit, dict) and unit.get("coverageStatus") != "VERIFIED"] + report = { + "schemaVersion": 1, + "status": "awaiting_exact_native_gate", + "pendingCount": len(pending), + "next": [ + { + "unitId": unit.get("id"), + "identifier": unit.get("identifier"), + "kind": unit.get("kind"), + "family": unit.get("family"), + "source": (unit.get("locations") or [{}])[0].get("path"), + "line": (unit.get("locations") or [{}])[0].get("line"), + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture", + } + for unit in pending[:64] + ], + } + write_json(CONTROL_ROOT / "unresolved-source-batches.json", report) + + def run_node(*args: str) -> None: result = subprocess.run(["node", *args], cwd=ROOT, text=True, capture_output=True, check=False) output = result.stdout or result.stderr @@ -1152,6 +1171,7 @@ def select_batch(inventory: dict) -> dict: if macro: return macro summary = pending_summary(inventory) + write_source_gap_report(inventory) write_planner_status({ "status": "waiting_for_exact_evidence", "reason": "no_configured_unresolved_source_batch", diff --git a/tests/golden/WBV2-P1419-001/manifest.json b/tests/golden/WBV2-P1419-001/manifest.json index 7e6ced802..8ce0f07d7 100644 --- a/tests/golden/WBV2-P1419-001/manifest.json +++ b/tests/golden/WBV2-P1419-001/manifest.json @@ -64,7 +64,7 @@ }, "status": { "path": "docs/status/WBV2-P1419-001.md", - "sha256": "18e34e498ee54efcf7a90eff10758dc1ad0dcfa2f205bfe17bc281707fe3cafd" + "sha256": "c52d993dc5724b0dc8ab84ea40bc600b2ce1249f35fbdf92b1cbfbe225f9e339" }, "log": { "path": "tests/golden/WBV2-P1419-001/module-run.log", diff --git a/tests/golden/WBV2/macro-binding-repair.json b/tests/golden/WBV2/macro-binding-repair.json new file mode 100644 index 000000000..78c9a407b --- /dev/null +++ b/tests/golden/WBV2/macro-binding-repair.json @@ -0,0 +1,138 @@ +{ + "schemaVersion": 1, + "operation": "REMOVE_FALSE_BROAD_MACRO_BINDINGS", + "removedBindingCount": 128, + "removedUnitIds": [ + "operator-macro:ACTION_OT_duplicate_move", + "operator-macro:ARMATURE_OT_duplicate_move", + "operator-macro:CURVES_OT_duplicate_move", + "operator-macro:CURVE_OT_duplicate_move", + "operator-macro:GRAPH_OT_duplicate_move", + "operator-macro:GREASE_PENCIL_OT_duplicate_move", + "operator-macro:MASK_OT_duplicate_move", + "operator-macro:MBALL_OT_duplicate_move", + "operator-macro:MESH_OT_duplicate_move", + "operator-macro:NLA_OT_duplicate_move", + "operator-macro:NODE_OT_duplicate_move", + "operator-macro:NODE_OT_duplicate_move_keep_inputs", + "operator-macro:NODE_OT_duplicate_move_linked", + "operator-macro:OBJECT_OT_duplicate_move", + "operator-macro:OBJECT_OT_duplicate_move_linked", + "operator-macro:POINTCLOUD_OT_duplicate_move", + "operator-macro:SEQUENCER_OT_duplicate_move", + "operator-macro:SEQUENCER_OT_duplicate_move_linked", + "operator-macro:SEQUENCER_OT_preview_duplicate_move", + "operator-macro:SEQUENCER_OT_preview_duplicate_move_linked", + "operator-macro:NODE_OT_delete_copy_reconnect", + "operator:ACTION_OT_delete", + "operator:ANIM_OT_channels_delete", + "operator:ANIM_OT_keyframe_delete", + "operator:ANIM_OT_keyframe_delete_button", + "operator:ANIM_OT_keyframe_delete_by_name", + "operator:ANIM_OT_keyframe_delete_v3d", + "operator:ANIM_OT_keyframe_delete_vse", + "operator:ARMATURE_OT_delete", + "operator:ASSET_OT_catalog_delete", + "operator:BRUSH_OT_asset_delete", + "operator:CLIP_OT_delete_marker", + "operator:CLIP_OT_delete_track", + "operator:CLIP_OT_graph_delete_curve", + "operator:CLIP_OT_graph_delete_knot", + "operator:CLIP_OT_keyframe_delete", + "operator:CONSOLE_OT_delete", + "operator:CONSTRAINT_OT_delete", + "operator:CURVES_OT_delete", + "operator:CURVE_OT_delete", + "operator:FILE_OT_bookmark_delete", + "operator:FILE_OT_delete", + "operator:FONT_OT_delete", + "operator:GPENCIL_OT_annotation_active_frame_delete", + "operator:GRAPH_OT_delete", + "operator:GRAPH_OT_driver_delete_invalid", + "operator:GRAPH_OT_fmodifier_delete", + "operator:GREASE_PENCIL_OT_active_frame_delete", + "operator:GREASE_PENCIL_OT_delete", + "operator:GREASE_PENCIL_OT_delete_breakdown", + "operator:GREASE_PENCIL_OT_delete_frame", + "operator:INFO_OT_report_delete", + "operator:MARKER_OT_delete", + "operator:MASK_OT_delete", + "operator:MBALL_OT_delete_metaelems", + "operator:MESH_OT_delete", + "operator:MESH_OT_delete_edgeloop", + "operator:MESH_OT_delete_loose", + "operator:MESH_OT_polybuild_delete_at_cursor", + "operator:NLA_OT_delete", + "operator:NLA_OT_tracks_delete", + "operator:NODE_OT_delete", + "operator:NODE_OT_delete_reconnect", + "operator:OBJECT_OT_multires_higher_levels_delete", + "operator:OBJECT_OT_vertex_weight_delete", + "operator:OUTLINER_OT_collection_hierarchy_delete", + "operator:OUTLINER_OT_delete", + "operator:OUTLINER_OT_drivers_delete_selected", + "operator:OUTLINER_OT_id_delete", + "operator:PAINTCURVE_OT_delete_point", + "operator:PALETTE_OT_color_delete", + "operator:PARTICLE_OT_delete", + "operator:POINTCLOUD_OT_delete", + "operator:SCENE_OT_delete", + "operator:SCREEN_OT_delete", + "operator:SEQUENCER_OT_delete", + "operator:SEQUENCER_OT_retiming_key_delete", + "operator:SEQUENCER_OT_text_delete", + "operator:TEXT_OT_delete", + "operator:TRANSFORM_OT_delete_orientation", + "operator:UI_OT_view_item_delete", + "operator:WORKSPACE_OT_delete", + "operator:WORKSPACE_OT_delete_all_others", + "operator:MASK_OT_hide_view_clear", + "operator:MASK_OT_hide_view_set", + "operator:POSE_OT_scale_clear", + "operator:OBJECT_OT_visual_transform_apply", + "operator:POSE_OT_visual_transform_apply", + "operator:ARMATURE_OT_move_to_collection", + "operator:ARMATURE_OT_parent_set", + "operator:MASK_OT_parent_set", + "operator:NODE_OT_parent_set", + "operator:OBJECT_OT_vertex_parent_set", + "operator:MESH_OT_primitive_cube_add_gizmo", + "operator-macro:ARMATURE_OT_extrude_forked", + "operator-macro:ARMATURE_OT_extrude_move", + "operator-macro:CURVES_OT_extrude_move", + "operator-macro:CURVE_OT_extrude_move", + "operator-macro:GREASE_PENCIL_OT_extrude_move", + "operator-macro:MESH_OT_extrude_context_move", + "operator-macro:MESH_OT_extrude_edges_move", + "operator-macro:MESH_OT_extrude_faces_move", + "operator-macro:MESH_OT_extrude_manifold", + "operator-macro:MESH_OT_extrude_region_move", + "operator-macro:MESH_OT_extrude_region_shrink_fatten", + "operator-macro:MESH_OT_extrude_vertices_move", + "operator-macro:MESH_OT_polybuild_extrude_at_cursor_move", + "operator:MESH_OT_dupli_extrude_cursor", + "operator:MESH_OT_extrude_context", + "operator:MESH_OT_extrude_edges_indiv", + "operator:MESH_OT_extrude_faces_indiv", + "operator:MESH_OT_extrude_repeat", + "operator:MESH_OT_extrude_verts_indiv", + "operator-macro:MESH_OT_loopcut_slide", + "operator:ARMATURE_OT_dissolve", + "operator:CURVE_OT_dissolve_verts", + "operator:GREASE_PENCIL_OT_dissolve", + "operator:MESH_OT_dissolve_degenerate", + "operator:MESH_OT_dissolve_faces", + "operator:MESH_OT_dissolve_limited", + "operator:MESH_OT_dissolve_mode", + "operator:MESH_OT_dissolve_verts", + "operator:MESH_OT_polybuild_dissolve_at_cursor", + "operator:ANIM_OT_merge_animation", + "operator:GREASE_PENCIL_OT_layer_merge", + "operator:GREASE_PENCIL_OT_stroke_merge_by_distance", + "operator:MESH_OT_merge_normals", + "operator:SCREEN_OT_edge_merge" + ], + "verifiedUnits": 1025, + "unverifiedUnits": 2720, + "rule": "macro names require an exact native command gate; family substring matches are forbidden" +} diff --git a/tests/golden/WBV2/unresolved-source-batches.json b/tests/golden/WBV2/unresolved-source-batches.json new file mode 100644 index 000000000..5a663dd07 --- /dev/null +++ b/tests/golden/WBV2/unresolved-source-batches.json @@ -0,0 +1,583 @@ +{ + "schemaVersion": 1, + "status": "awaiting_exact_native_gate", + "pendingCount": 2720, + "next": [ + { + "unitId": "modifier-source:MOD_none", + "identifier": "MOD_none", + "kind": "modifier-source", + "family": "MODIFIER", + "source": "blender-5.2.0/source/blender/modifiers/intern/MOD_none.cc", + "line": 1, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "modifier-source:MOD_ui_common", + "identifier": "MOD_ui_common", + "kind": "modifier-source", + "family": "MODIFIER", + "source": "blender-5.2.0/source/blender/modifiers/intern/MOD_ui_common.cc", + "line": 1, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:ACTION_OT_duplicate_move", + "identifier": "ACTION_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_action/action_ops.cc", + "line": 80, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:ARMATURE_OT_duplicate_move", + "identifier": "ARMATURE_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/armature/armature_ops.cc", + "line": 135, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:ARMATURE_OT_extrude_forked", + "identifier": "ARMATURE_OT_extrude_forked", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/armature/armature_ops.cc", + "line": 156, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:ARMATURE_OT_extrude_move", + "identifier": "ARMATURE_OT_extrude_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/armature/armature_ops.cc", + "line": 144, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:CLIP_OT_add_marker_move", + "identifier": "CLIP_OT_add_marker_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_clip/clip_ops.cc", + "line": 1894, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:CLIP_OT_add_marker_slide", + "identifier": "CLIP_OT_add_marker_slide", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_clip/clip_ops.cc", + "line": 1902, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:CURVES_OT_duplicate_move", + "identifier": "CURVES_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/curves/intern/curves_ops.cc", + "line": 1886, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:CURVES_OT_extrude_move", + "identifier": "CURVES_OT_extrude_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/curves/intern/curves_ops.cc", + "line": 1895, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:CURVE_OT_duplicate_move", + "identifier": "CURVE_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/curve/curve_ops.cc", + "line": 129, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:CURVE_OT_extrude_move", + "identifier": "CURVE_OT_extrude_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/curve/curve_ops.cc", + "line": 138, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:GRAPH_OT_duplicate_move", + "identifier": "GRAPH_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_graph/graph_ops.cc", + "line": 517, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:GREASE_PENCIL_OT_duplicate_move", + "identifier": "GREASE_PENCIL_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/grease_pencil/intern/grease_pencil_ops.cc", + "line": 335, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:GREASE_PENCIL_OT_extrude_move", + "identifier": "GREASE_PENCIL_OT_extrude_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/grease_pencil/intern/grease_pencil_ops.cc", + "line": 354, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:GREASE_PENCIL_OT_stroke_subdivide_smooth", + "identifier": "GREASE_PENCIL_OT_stroke_subdivide_smooth", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/grease_pencil/intern/grease_pencil_ops.cc", + "line": 346, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MASK_OT_add_feather_vertex_slide", + "identifier": "MASK_OT_add_feather_vertex_slide", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mask/mask_edit.cc", + "line": 184, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MASK_OT_add_vertex_slide", + "identifier": "MASK_OT_add_vertex_slide", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mask/mask_edit.cc", + "line": 175, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MASK_OT_duplicate_move", + "identifier": "MASK_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mask/mask_edit.cc", + "line": 193, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MBALL_OT_duplicate_move", + "identifier": "MBALL_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/metaball/mball_ops.cc", + "line": 39, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_duplicate_move", + "identifier": "MESH_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 236, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_extrude_context_move", + "identifier": "MESH_OT_extrude_context_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 284, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_extrude_edges_move", + "identifier": "MESH_OT_extrude_edges_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 311, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_extrude_faces_move", + "identifier": "MESH_OT_extrude_faces_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 302, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_extrude_manifold", + "identifier": "MESH_OT_extrude_manifold", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 272, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_extrude_region_move", + "identifier": "MESH_OT_extrude_region_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 263, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_extrude_region_shrink_fatten", + "identifier": "MESH_OT_extrude_region_shrink_fatten", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 293, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_extrude_vertices_move", + "identifier": "MESH_OT_extrude_vertices_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 320, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_loopcut_slide", + "identifier": "MESH_OT_loopcut_slide", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 221, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_offset_edge_loops_slide", + "identifier": "MESH_OT_offset_edge_loops_slide", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 228, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_polybuild_extrude_at_cursor_move", + "identifier": "MESH_OT_polybuild_extrude_at_cursor_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 356, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_polybuild_face_at_cursor_move", + "identifier": "MESH_OT_polybuild_face_at_cursor_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 329, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_polybuild_split_at_cursor_move", + "identifier": "MESH_OT_polybuild_split_at_cursor_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 338, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_polybuild_transform_at_cursor_move", + "identifier": "MESH_OT_polybuild_transform_at_cursor_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 347, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_rip_edge_move", + "identifier": "MESH_OT_rip_edge_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 254, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:MESH_OT_rip_move", + "identifier": "MESH_OT_rip_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/mesh/mesh_ops.cc", + "line": 245, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NLA_OT_duplicate_linked_move", + "identifier": "NLA_OT_duplicate_linked_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_nla/nla_ops.cc", + "line": 166, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NLA_OT_duplicate_move", + "identifier": "NLA_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_nla/nla_ops.cc", + "line": 157, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NODE_OT_delete_copy_reconnect", + "identifier": "NODE_OT_delete_copy_reconnect", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_node/node_ops.cc", + "line": 241, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NODE_OT_detach_translate_attach", + "identifier": "NODE_OT_detach_translate_attach", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_node/node_ops.cc", + "line": 193, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NODE_OT_duplicate_move", + "identifier": "NODE_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_node/node_ops.cc", + "line": 201, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NODE_OT_duplicate_move_keep_inputs", + "identifier": "NODE_OT_duplicate_move_keep_inputs", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_node/node_ops.cc", + "line": 219, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NODE_OT_duplicate_move_linked", + "identifier": "NODE_OT_duplicate_move_linked", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_node/node_ops.cc", + "line": 209, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NODE_OT_join_named", + "identifier": "NODE_OT_join_named", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_node/node_ops.cc", + "line": 162, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NODE_OT_move_detach_links", + "identifier": "NODE_OT_move_detach_links", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_node/node_ops.cc", + "line": 227, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NODE_OT_move_detach_links_release", + "identifier": "NODE_OT_move_detach_links_release", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_node/node_ops.cc", + "line": 234, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NODE_OT_select_link_viewer", + "identifier": "NODE_OT_select_link_viewer", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_node/node_ops.cc", + "line": 152, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NODE_OT_translate_attach", + "identifier": "NODE_OT_translate_attach", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_node/node_ops.cc", + "line": 172, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:NODE_OT_translate_attach_remove_on_cancel", + "identifier": "NODE_OT_translate_attach_remove_on_cancel", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_node/node_ops.cc", + "line": 180, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:OBJECT_OT_duplicate_move", + "identifier": "OBJECT_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/object/object_ops.cc", + "line": 306, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:OBJECT_OT_duplicate_move_linked", + "identifier": "OBJECT_OT_duplicate_move_linked", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/object/object_ops.cc", + "line": 316, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:PAINTCURVE_OT_add_point_slide", + "identifier": "PAINTCURVE_OT_add_point_slide", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/sculpt_paint/paint_ops.cc", + "line": 553, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:POINTCLOUD_OT_duplicate_move", + "identifier": "POINTCLOUD_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/pointcloud/intern/operators.cc", + "line": 255, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:SEQUENCER_OT_duplicate_move", + "identifier": "SEQUENCER_OT_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_sequencer/sequencer_ops.cc", + "line": 169, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:SEQUENCER_OT_duplicate_move_linked", + "identifier": "SEQUENCER_OT_duplicate_move_linked", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_sequencer/sequencer_ops.cc", + "line": 176, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:SEQUENCER_OT_preview_duplicate_move", + "identifier": "SEQUENCER_OT_preview_duplicate_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_sequencer/sequencer_ops.cc", + "line": 184, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:SEQUENCER_OT_preview_duplicate_move_linked", + "identifier": "SEQUENCER_OT_preview_duplicate_move_linked", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_sequencer/sequencer_ops.cc", + "line": 191, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:SEQUENCER_OT_retiming_add_freeze_frame_slide", + "identifier": "SEQUENCER_OT_retiming_add_freeze_frame_slide", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_sequencer/sequencer_ops.cc", + "line": 199, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:SEQUENCER_OT_retiming_add_transition_slide", + "identifier": "SEQUENCER_OT_retiming_add_transition_slide", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_sequencer/sequencer_ops.cc", + "line": 206, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator-macro:UV_OT_rip_move", + "identifier": "UV_OT_rip_move", + "kind": "operator-macro", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/uvedit/uvedit_ops.cc", + "line": 2989, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator:ACTION_OT_bake_keys", + "identifier": "ACTION_OT_bake_keys", + "kind": "operator", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_action/action_ops.cc", + "line": 52, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator:ACTION_OT_clean", + "identifier": "ACTION_OT_clean", + "kind": "operator", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_action/action_ops.cc", + "line": 53, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator:ACTION_OT_clickselect", + "identifier": "ACTION_OT_clickselect", + "kind": "operator", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_action/action_ops.cc", + "line": 31, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + }, + { + "unitId": "operator:ACTION_OT_copy", + "identifier": "ACTION_OT_copy", + "kind": "operator", + "family": "EDITOR", + "source": "blender-5.2.0/source/blender/editors/space_action/action_ops.cc", + "line": 57, + "required": "real Blender Main/WASM command adapter plus exact Chromium fixture" + } + ] +} diff --git a/tools/web/repair-wbv2-macro-bindings.mjs b/tools/web/repair-wbv2-macro-bindings.mjs new file mode 100644 index 000000000..098a4b79e --- /dev/null +++ b/tools/web/repair-wbv2-macro-bindings.mjs @@ -0,0 +1,83 @@ +import fs from "node:fs"; +import path from "node:path"; +import crypto from "node:crypto"; +import { fileURLToPath } from "node:url"; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); +const abs = (file) => path.join(root, file); +const readJson = (file) => JSON.parse(fs.readFileSync(abs(file), "utf8")); +const sha = (file) => crypto.createHash("sha256").update(fs.readFileSync(abs(file))).digest("hex"); +const writeJson = (file, value) => fs.writeFileSync(abs(file), `${JSON.stringify(value, null, 2)}\n`); + +const bindingsPath = "tests/golden/WBV2/dynamic-coverage-bindings.json"; +const inventoryPath = "tests/golden/WBV2/dynamic-inventory.json"; +const coverageManifestPath = "tests/golden/WBV2/dynamic-coverage-manifest.json"; +const inventoryManifestPath = "tests/golden/WBV2/dynamic-inventory-manifest.json"; +const auditPath = "tests/golden/WBV2/dynamic-coverage-audit.json"; +const repairPath = "tests/golden/WBV2/macro-binding-repair.json"; + +const bindings = readJson(bindingsPath); +const inventory = readJson(inventoryPath); +const macroTasks = new Set(); +const index = readJson("tests/golden/WBV2/task-index.json"); +const plan = readJson(index.source.path); +for (const task of plan.tasks ?? []) { + if (String(task.module?.moduleId ?? "").endsWith("_MACRO_BATCH")) macroTasks.add(task.id); +} +const removed = bindings.filter((binding) => macroTasks.has(binding.task) || String(binding.capabilityId ?? "").endsWith("_MACRO_BATCH")); +const kept = bindings.filter((binding) => !macroTasks.has(binding.task) && !String(binding.capabilityId ?? "").endsWith("_MACRO_BATCH")); +const removedIds = new Set(removed.map((binding) => binding.unitId)); +const updatedUnits = inventory.units.map((unit) => { + if (!removedIds.has(unit.id)) return unit; + const { coverage, ...withoutCoverage } = unit; + return { ...withoutCoverage, coverageStatus: "UNVERIFIED" }; +}); +const verifiedUnits = updatedUnits.filter((unit) => unit.coverageStatus === "VERIFIED").length; +const updatedInventory = { + ...inventory, + units: updatedUnits, + coverage: { ...inventory.coverage, verifiedUnits, unverifiedUnits: inventory.summary.unitCount - verifiedUnits }, + coverageLedger: kept, +}; +writeJson(bindingsPath, kept); +writeJson(inventoryPath, updatedInventory); +const refresh = (file) => { + if (!fs.existsSync(abs(file))) return; + const value = readJson(file); + if (file === coverageManifestPath) { + value.artifacts.inventory.sha256 = sha(inventoryPath); + value.artifacts.bindings.sha256 = sha(bindingsPath); + value.coverage = { ...value.coverage, verifiedUnits, unverifiedUnits: inventory.summary.unitCount - verifiedUnits, boundUnitDelta: -removed.length }; + } else if (file === inventoryManifestPath) { + value.artifacts.inventory.sha256 = sha(inventoryPath); + value.inventory = { ...value.inventory, verifiedUnits, unverifiedUnits: inventory.summary.unitCount - verifiedUnits, boundCaseDelta: -removed.length }; + } else { + const coverageByKind = {}; + const coverageByFamily = {}; + for (const unit of updatedUnits) { + const kind = coverageByKind[unit.kind] ??= { verified: 0, unverified: 0 }; + const family = coverageByFamily[unit.family] ??= { verified: 0, unverified: 0 }; + const key = unit.coverageStatus === "VERIFIED" ? "verified" : "unverified"; + kind[key] += 1; + family[key] += 1; + } + value.dynamicInventory = { ...(value.dynamicInventory ?? {}), afterSha256: sha(inventoryPath), verifiedUnits, unverifiedUnits: inventory.summary.unitCount - verifiedUnits }; + value.coverageByKind = coverageByKind; + value.coverageByFamily = coverageByFamily; + value.explicitBindings = kept; + } + writeJson(file, value); +}; +refresh(coverageManifestPath); +refresh(inventoryManifestPath); +refresh(auditPath); +writeJson(repairPath, { + schemaVersion: 1, + operation: "REMOVE_FALSE_BROAD_MACRO_BINDINGS", + removedBindingCount: removed.length, + removedUnitIds: [...removedIds], + verifiedUnits, + unverifiedUnits: inventory.summary.unitCount - verifiedUnits, + rule: "macro names require an exact native command gate; family substring matches are forbidden", +}); +process.stdout.write(`macro-binding-repair removed=${removed.length} verified=${verifiedUnits} unverified=${inventory.summary.unitCount - verifiedUnits}\n`);