fix(web): reject false macro coverage and record source gaps
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-05 18:35:18 +08:00
parent 60ac88cc86
commit 9ec6d4d28f
5 changed files with 843 additions and 19 deletions

View File

@@ -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",

View File

@@ -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",

View File

@@ -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"
}

View File

@@ -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"
}
]
}

View File

@@ -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`);